blob: 296b42fd2fd6495a2b7664d0f6b88cc0f39ce0c1 [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"
26 "strconv"
27 "syscall"
28 "time"
29
Esin Karamanccb714b2019-11-29 15:02:06 +000030 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
kdarapu381c6902019-07-31 18:23:16 +053031
Esin Karamanccb714b2019-11-29 15:02:06 +000032 "github.com/opencord/voltha-lib-go/v3/pkg/adapters"
33 com "github.com/opencord/voltha-lib-go/v3/pkg/adapters/common"
divyadesaia37f78b2020-02-07 12:41:22 +000034 conf "github.com/opencord/voltha-lib-go/v3/pkg/config"
Esin Karamanccb714b2019-11-29 15:02:06 +000035 "github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
36 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
37 "github.com/opencord/voltha-lib-go/v3/pkg/log"
38 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
Girish Gowdru0c588b22019-04-23 23:24:56 -040039 ac "github.com/opencord/voltha-openolt-adapter/adaptercore"
40 "github.com/opencord/voltha-openolt-adapter/config"
Matt Jeanneret0c9ae282019-07-18 18:14:28 -040041 "github.com/opencord/voltha-openolt-adapter/config/version"
Esin Karamanccb714b2019-11-29 15:02:06 +000042 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
43 "github.com/opencord/voltha-protos/v3/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
55 eventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070056 halted bool
57 exitChannel chan int
58 receiverChannels []<-chan *ic.InterContainerMessage
59}
60
61func init() {
Matteo Scandolo945e4012019-12-12 14:16:11 -080062 _, _ = log.AddPackage(log.CONSOLE, log.DebugLevel, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -070063}
64
65func newAdapter(cf *config.AdapterFlags) *adapter {
66 var a adapter
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067 a.instanceID = cf.InstanceID
cuilin20187b2a8c32019-03-26 19:52:28 -070068 a.config = cf
69 a.halted = false
70 a.exitChannel = make(chan int, 1)
71 a.receiverChannels = make([]<-chan *ic.InterContainerMessage, 0)
72 return &a
73}
74
75func (a *adapter) start(ctx context.Context) {
76 log.Info("Starting Core Adapter components")
77 var err error
78
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000079 var p *probe.Probe
80 if value := ctx.Value(probe.ProbeContextKey); value != nil {
81 if _, ok := value.(*probe.Probe); ok {
82 p = value.(*probe.Probe)
83 p.RegisterService(
84 "message-bus",
85 "kv-store",
86 "container-proxy",
87 "core-request-handler",
88 "register-with-core",
89 )
90 }
91 }
92
cuilin20187b2a8c32019-03-26 19:52:28 -070093 // Setup KV Client
94 log.Debugw("create-kv-client", log.Fields{"kvstore": a.config.KVStoreType})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070095 if err = a.setKVClient(); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -070096 log.Fatal("error-setting-kv-client")
97 }
98
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000099 if p != nil {
100 p.UpdateStatus("kv-store", probe.ServiceStatusRunning)
101 }
102
divyadesaia37f78b2020-02-07 12:41:22 +0000103 // Setup Log Config
104 cm := conf.NewConfigManager(a.kvClient, a.config.KVStoreType, a.config.KVStoreHost, a.config.KVStorePort, a.config.KVStoreTimeout)
105 go conf.ProcessLogConfigChange(cm, ctx)
106
cuilin20187b2a8c32019-03-26 19:52:28 -0700107 // Setup Kafka Client
108 if a.kafkaClient, err = newKafkaClient("sarama", a.config.KafkaAdapterHost, a.config.KafkaAdapterPort); err != nil {
109 log.Fatal("Unsupported-common-client")
110 }
111
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000112 if p != nil {
113 p.UpdateStatus("message-bus", probe.ServiceStatusRunning)
114 }
115
cuilin20187b2a8c32019-03-26 19:52:28 -0700116 // Start the common InterContainer Proxy - retries indefinitely
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000117 if a.kip, err = a.startInterContainerProxy(ctx, -1); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700118 log.Fatal("error-starting-inter-container-proxy")
119 }
120
121 // Create the core proxy to handle requests to the Core
122 a.coreProxy = com.NewCoreProxy(a.kip, a.config.Topic, a.config.CoreTopic)
123
124 // Create the adaptor proxy to handle request between olt and onu
125 a.adapterProxy = com.NewAdapterProxy(a.kip, "brcm_openomci_onu", a.config.CoreTopic)
126
Devmalya Paulfb990a52019-07-09 10:01:49 -0400127 // Create the event proxy to post events to KAFKA
128 a.eventProxy = com.NewEventProxy(com.MsgClient(a.kafkaClient), com.MsgTopic(kafka.Topic{Name: a.config.EventTopic}))
129
cuilin20187b2a8c32019-03-26 19:52:28 -0700130 // Create the open OLT adapter
kdarapu381c6902019-07-31 18:23:16 +0530131 if a.iAdapter, err = a.startOpenOLT(ctx, a.kip, a.coreProxy, a.adapterProxy, a.eventProxy,
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530132 a.config); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700133 log.Fatal("error-starting-inter-container-proxy")
134 }
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 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700138 log.Fatal("error-setting-core-request-handler")
139 }
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 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700143 log.Fatal("error-registering-with-core")
144 }
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:
191 // Check the status of the kv-store
192 log.Info("kv-store liveliness-recheck")
npujarec5762e2020-01-01 14:08:48 +0530193 if a.kvClient.IsConnectionUp(ctx) {
cbabu116b73f2019-12-10 17:56:32 +0530194 kvStoreChannel <- true
195 } else {
196 kvStoreChannel <- false
197 }
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) {
207 livelinessChannel := a.kafkaClient.EnableLivenessChannel(true)
Scott Baker86fce9a2019-12-12 09:47:17 -0800208 healthinessChannel := a.kafkaClient.EnableHealthinessChannel(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:
245 log.Info("kafka-proxy-liveness-recheck")
246 // 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.
248 err := a.kafkaClient.SendLiveness()
249 if err != nil {
250 // Catch possible error case if sending liveness after Sarama has been stopped.
251 log.Warnw("error-kafka-send-liveness", log.Fields{"error": err})
252 }
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 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700268 log.Infow("fail-to-release-all-reservations", log.Fields{"error": err})
269 }
270 // Close the DB connection
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700271 a.kvClient.Close()
cuilin20187b2a8c32019-03-26 19:52:28 -0700272 }
273
Scott Bakere701b862020-02-20 16:19:16 -0800274 if a.kip != nil {
275 a.kip.Stop()
276 }
277
cuilin20187b2a8c32019-03-26 19:52:28 -0700278 // TODO: More cleanup
279}
280
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700281func newKVClient(storeType, address string, timeout int) (kvstore.Client, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700282
283 log.Infow("kv-store-type", log.Fields{"store": storeType})
284 switch storeType {
285 case "consul":
286 return kvstore.NewConsulClient(address, timeout)
287 case "etcd":
288 return kvstore.NewEtcdClient(address, timeout)
289 }
290 return nil, errors.New("unsupported-kv-store")
291}
292
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700293func newKafkaClient(clientType, host string, port int) (kafka.Client, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700294
295 log.Infow("common-client-type", log.Fields{"client": clientType})
296 switch clientType {
297 case "sarama":
298 return kafka.NewSaramaClient(
299 kafka.Host(host),
300 kafka.Port(port),
301 kafka.ProducerReturnOnErrors(true),
302 kafka.ProducerReturnOnSuccess(true),
303 kafka.ProducerMaxRetries(6),
Abhilash S.L3b494632019-07-16 15:51:09 +0530304 kafka.ProducerRetryBackoff(time.Millisecond*30),
305 kafka.MetadatMaxRetries(15)), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700306 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700307
cuilin20187b2a8c32019-03-26 19:52:28 -0700308 return nil, errors.New("unsupported-client-type")
309}
310
311func (a *adapter) setKVClient() error {
312 addr := a.config.KVStoreHost + ":" + strconv.Itoa(a.config.KVStorePort)
313 client, err := newKVClient(a.config.KVStoreType, addr, a.config.KVStoreTimeout)
314 if err != nil {
315 a.kvClient = nil
316 log.Error(err)
317 return err
318 }
319 a.kvClient = client
divyadesaia37f78b2020-02-07 12:41:22 +0000320
cuilin20187b2a8c32019-03-26 19:52:28 -0700321 return nil
322}
323
npujarec5762e2020-01-01 14:08:48 +0530324func (a *adapter) startInterContainerProxy(ctx context.Context, retries int) (kafka.InterContainerProxy, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700325 log.Infow("starting-intercontainer-messaging-proxy", log.Fields{"host": a.config.KafkaAdapterHost,
326 "port": a.config.KafkaAdapterPort, "topic": a.config.Topic})
327 var err error
npujarec5762e2020-01-01 14:08:48 +0530328 kip := kafka.NewInterContainerProxy(
cuilin20187b2a8c32019-03-26 19:52:28 -0700329 kafka.InterContainerHost(a.config.KafkaAdapterHost),
330 kafka.InterContainerPort(a.config.KafkaAdapterPort),
331 kafka.MsgClient(a.kafkaClient),
npujarec5762e2020-01-01 14:08:48 +0530332 kafka.DefaultTopic(&kafka.Topic{Name: a.config.Topic}))
cuilin20187b2a8c32019-03-26 19:52:28 -0700333 count := 0
334 for {
335 if err = kip.Start(); err != nil {
336 log.Warnw("error-starting-messaging-proxy", log.Fields{"error": err})
337 if retries == count {
338 return nil, err
339 }
340 count = +1
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700341 // Take a nap before retrying
cuilin20187b2a8c32019-03-26 19:52:28 -0700342 time.Sleep(2 * time.Second)
343 } else {
344 break
345 }
346 }
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000347 probe.UpdateStatusFromContext(ctx, "container-proxy", probe.ServiceStatusRunning)
cuilin20187b2a8c32019-03-26 19:52:28 -0700348 log.Info("common-messaging-proxy-created")
349 return kip, nil
350}
351
npujarec5762e2020-01-01 14:08:48 +0530352func (a *adapter) startOpenOLT(ctx context.Context, kip kafka.InterContainerProxy,
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530353 cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy,
354 cfg *config.AdapterFlags) (*ac.OpenOLT, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700355 log.Info("starting-open-olt")
356 var err error
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530357 sOLT := ac.NewOpenOLT(ctx, a.kip, cp, ap, ep, cfg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700358
359 if err = sOLT.Start(ctx); err != nil {
360 log.Fatalw("error-starting-messaging-proxy", log.Fields{"error": err})
361 return nil, err
362 }
363
364 log.Info("open-olt-started")
365 return sOLT, nil
366}
367
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000368func (a *adapter) setupRequestHandler(ctx context.Context, coreInstanceID string, iadapter adapters.IAdapter) error {
cuilin20187b2a8c32019-03-26 19:52:28 -0700369 log.Info("setting-request-handler")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700370 requestProxy := com.NewRequestHandlerProxy(coreInstanceID, iadapter, a.coreProxy)
cuilin20187b2a8c32019-03-26 19:52:28 -0700371 if err := a.kip.SubscribeWithRequestHandlerInterface(kafka.Topic{Name: a.config.Topic}, requestProxy); err != nil {
372 log.Errorw("request-handler-setup-failed", log.Fields{"error": err})
373 return err
374
375 }
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000376 probe.UpdateStatusFromContext(ctx, "core-request-handler", probe.ServiceStatusRunning)
cuilin20187b2a8c32019-03-26 19:52:28 -0700377 log.Info("request-handler-setup-done")
378 return nil
379}
380
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000381func (a *adapter) registerWithCore(ctx context.Context, retries int) error {
cuilin20187b2a8c32019-03-26 19:52:28 -0700382 log.Info("registering-with-core")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400383 adapterDescription := &voltha.Adapter{Id: "openolt", // Unique name for the device type
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400384 Vendor: "VOLTHA OpenOLT",
385 Version: version.VersionInfo.Version}
Girish Gowdru0c588b22019-04-23 23:24:56 -0400386 types := []*voltha.DeviceType{{Id: "openolt",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700387 Adapter: "openolt", // Name of the adapter that handles device type
Girish Gowdru0c588b22019-04-23 23:24:56 -0400388 AcceptsBulkFlowUpdate: false, // Currently openolt adapter does not support bulk flow handling
389 AcceptsAddRemoveFlowUpdates: true}}
cuilin20187b2a8c32019-03-26 19:52:28 -0700390 deviceTypes := &voltha.DeviceTypes{Items: types}
391 count := 0
392 for {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700393 if err := a.coreProxy.RegisterAdapter(context.TODO(), adapterDescription, deviceTypes); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700394 log.Warnw("registering-with-core-failed", log.Fields{"error": err})
395 if retries == count {
396 return err
397 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700398 count++
399 // Take a nap before retrying
cuilin20187b2a8c32019-03-26 19:52:28 -0700400 time.Sleep(2 * time.Second)
401 } else {
402 break
403 }
404 }
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000405 probe.UpdateStatusFromContext(ctx, "register-with-core", probe.ServiceStatusRunning)
cuilin20187b2a8c32019-03-26 19:52:28 -0700406 log.Info("registered-with-core")
407 return nil
408}
409
410func waitForExit() int {
411 signalChannel := make(chan os.Signal, 1)
412 signal.Notify(signalChannel,
413 syscall.SIGHUP,
414 syscall.SIGINT,
415 syscall.SIGTERM,
416 syscall.SIGQUIT)
417
418 exitChannel := make(chan int)
419
420 go func() {
421 s := <-signalChannel
422 switch s {
423 case syscall.SIGHUP,
424 syscall.SIGINT,
425 syscall.SIGTERM,
426 syscall.SIGQUIT:
427 log.Infow("closing-signal-received", log.Fields{"signal": s})
428 exitChannel <- 0
429 default:
430 log.Infow("unexpected-signal-received", log.Fields{"signal": s})
431 exitChannel <- 1
432 }
433 }()
434
435 code := <-exitChannel
436 return code
437}
438
439func printBanner() {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800440 fmt.Println(` ____ ____ _ _______ `)
441 fmt.Println(` / _ \ / __ \| | |__ __|`)
442 fmt.Println(` | | | |_ __ ___ _ __ | | | | | | | `)
443 fmt.Println(` | | | | '_ \ / _ \ '_ \ | | | | | | | `)
444 fmt.Println(` | |__| | |_) | __/ | | || |__| | |____| | `)
445 fmt.Println(` \____/| .__/ \___|_| |_| \____/|______|_| `)
446 fmt.Println(` | | `)
447 fmt.Println(` |_| `)
448 fmt.Println(` `)
cuilin20187b2a8c32019-03-26 19:52:28 -0700449}
450
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400451func printVersion() {
452 fmt.Println("VOLTHA OpenOLT Adapter")
453 fmt.Println(version.VersionInfo.String(" "))
454}
455
cuilin20187b2a8c32019-03-26 19:52:28 -0700456func main() {
457 start := time.Now()
458
459 cf := config.NewAdapterFlags()
460 cf.ParseCommandArguments()
461
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700462 // Setup logging
cuilin20187b2a8c32019-03-26 19:52:28 -0700463
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000464 logLevel, err := log.StringToLogLevel(cf.LogLevel)
465 if err != nil {
466 log.Fatalf("Cannot setup logging, %s", err)
467 }
Rohan Agrawal2488f192020-01-31 09:26:55 +0000468
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700469 // Setup default logger - applies for packages that do not have specific logger set
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000470 if _, err := log.SetDefaultLogger(log.JSON, logLevel, log.Fields{"instanceId": cf.InstanceID}); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700471 log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
472 }
473
474 // Update all loggers (provisionned via init) with a common field
Hardik Windlassb9c869b2019-10-10 08:34:32 +0000475 if err := log.UpdateAllLoggers(log.Fields{"instanceId": cf.InstanceID}); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700476 log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
477 }
478
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000479 log.SetAllLogLevel(logLevel)
Rohan Agrawal93bced32020-02-11 10:16:01 +0000480
cuilin20187b2a8c32019-03-26 19:52:28 -0700481 defer log.CleanUp()
482
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400483 // Print version / build information and exit
484 if cf.DisplayVersionOnly {
485 printVersion()
486 return
487 }
488
cuilin20187b2a8c32019-03-26 19:52:28 -0700489 // Print banner if specified
490 if cf.Banner {
491 printBanner()
492 }
493
494 log.Infow("config", log.Fields{"config": *cf})
495
496 ctx, cancel := context.WithCancel(context.Background())
497 defer cancel()
498
499 ad := newAdapter(cf)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000500
501 p := &probe.Probe{}
502 go p.ListenAndServe(fmt.Sprintf("%s:%d", ad.config.ProbeHost, ad.config.ProbePort))
503
504 probeCtx := context.WithValue(ctx, probe.ProbeContextKey, p)
505
506 go ad.start(probeCtx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700507
508 code := waitForExit()
509 log.Infow("received-a-closing-signal", log.Fields{"code": code})
510
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)
Hardik Windlassb9c869b2019-10-10 08:34:32 +0000515 log.Infow("run-time", log.Fields{"instanceId": ad.config.InstanceID, "time": elapsed / time.Second})
cuilin20187b2a8c32019-03-26 19:52:28 -0700516}