blob: f495aeb9169704b9495ee3450e1a3d3a8f050099 [file] [log] [blame]
khenaidoobf6e7bb2018-08-14 22:27:29 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * 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
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * 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.
15 */
khenaidoocfee5f42018-07-19 22:47:38 -040016package main
17
18import (
khenaidoo5c11af72018-07-20 17:21:05 -040019 "context"
20 "errors"
khenaidoocfee5f42018-07-19 22:47:38 -040021 "fmt"
khenaidoobf6e7bb2018-08-14 22:27:29 -040022 grpcserver "github.com/opencord/voltha-go/common/grpc"
khenaidoo5c11af72018-07-20 17:21:05 -040023 "github.com/opencord/voltha-go/common/log"
24 "github.com/opencord/voltha-go/db/kvstore"
khenaidooabad44c2018-08-03 16:58:35 -040025 "github.com/opencord/voltha-go/kafka"
26 ca "github.com/opencord/voltha-go/protos/core_adapter"
khenaidoobf6e7bb2018-08-14 22:27:29 -040027 "github.com/opencord/voltha-go/protos/voltha"
khenaidoo5c11af72018-07-20 17:21:05 -040028 "github.com/opencord/voltha-go/rw_core/config"
khenaidoobf6e7bb2018-08-14 22:27:29 -040029 grpcapi "github.com/opencord/voltha-go/rw_core/nbi/grpc"
30 "google.golang.org/grpc"
khenaidoocfee5f42018-07-19 22:47:38 -040031 "os"
32 "os/signal"
khenaidoocfee5f42018-07-19 22:47:38 -040033 "strconv"
khenaidoocfee5f42018-07-19 22:47:38 -040034 "syscall"
khenaidoo5c11af72018-07-20 17:21:05 -040035 "time"
khenaidoocfee5f42018-07-19 22:47:38 -040036)
37
38type rwCore struct {
khenaidoo5c11af72018-07-20 17:21:05 -040039 kvClient kvstore.Client
40 config *config.RWCoreFlags
41 halted bool
42 exitChannel chan int
khenaidooabad44c2018-08-03 16:58:35 -040043 kmp *kafka.KafkaMessagingProxy
khenaidoobf6e7bb2018-08-14 22:27:29 -040044 grpcServer *grpcserver.GrpcServer
khenaidooabad44c2018-08-03 16:58:35 -040045 //For test
46 receiverChannels []<-chan *ca.InterContainerMessage
khenaidoocfee5f42018-07-19 22:47:38 -040047}
48
49func newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
50
khenaidoo5c11af72018-07-20 17:21:05 -040051 log.Infow("kv-store-type", log.Fields{"store": storeType})
khenaidoocfee5f42018-07-19 22:47:38 -040052 switch storeType {
53 case "consul":
54 return kvstore.NewConsulClient(address, timeout)
55 case "etcd":
56 return kvstore.NewEtcdClient(address, timeout)
57 }
58 return nil, errors.New("unsupported-kv-store")
59}
60
61func newRWCore(cf *config.RWCoreFlags) *rwCore {
62 var rwCore rwCore
63 rwCore.config = cf
64 rwCore.halted = false
65 rwCore.exitChannel = make(chan int, 1)
khenaidooabad44c2018-08-03 16:58:35 -040066 rwCore.receiverChannels = make([]<-chan *ca.InterContainerMessage, 0)
khenaidoocfee5f42018-07-19 22:47:38 -040067 return &rwCore
68}
69
70func (core *rwCore) setKVClient() error {
71 addr := core.config.KVStoreHost + ":" + strconv.Itoa(core.config.KVStorePort)
72 client, err := newKVClient(core.config.KVStoreType, addr, core.config.KVStoreTimeout)
73 if err != nil {
74 log.Error(err)
75 return err
76 }
77 core.kvClient = client
78 return nil
79}
80
khenaidoocfee5f42018-07-19 22:47:38 -040081func toString(value interface{}) (string, error) {
82 switch t := value.(type) {
83 case []byte:
84 return string(value.([]byte)), nil
85 case string:
86 return value.(string), nil
87 default:
88 return "", fmt.Errorf("unexpected-type-%T", t)
89 }
90}
91
khenaidoobf6e7bb2018-08-14 22:27:29 -040092func (core *rwCore) startGRPCService(context.Context) {
93 // create an insecure gserver server
94 core.grpcServer = grpcserver.NewGrpcServer(core.config.GrpcHost, core.config.GrpcPort, nil, false)
95 log.Info("server created")
96 //
97 // Create a function to register the core GRPC service with the GRPC server
98 f := func(gs *grpc.Server) {
99 voltha.RegisterVolthaServiceServer(
100 gs,
101 grpcapi.NewAPIHandler(),
102 )
103 }
104
105 core.grpcServer.AddService(f)
106 log.Info("service add")
107
108 // Start the server
109 core.grpcServer.Start(context.Background())
110 log.Info("server started")
111}
112
khenaidooabad44c2018-08-03 16:58:35 -0400113
khenaidoo5c11af72018-07-20 17:21:05 -0400114func (core *rwCore) start(ctx context.Context) {
115 log.Info("Starting RW Core components")
116 // Setup GRPC Server
khenaidoobf6e7bb2018-08-14 22:27:29 -0400117 go core.startGRPCService(ctx)
khenaidoocfee5f42018-07-19 22:47:38 -0400118
khenaidoo5c11af72018-07-20 17:21:05 -0400119 // Setup KV Client
khenaidoocfee5f42018-07-19 22:47:38 -0400120
khenaidoo5c11af72018-07-20 17:21:05 -0400121 // Setup Kafka messaging services
khenaidooabad44c2018-08-03 16:58:35 -0400122 var err error
123 if core.kmp, err = kafka.NewKafkaMessagingProxy(
124 kafka.KafkaHost("10.100.198.220"),
125 kafka.KafkaPort(9092),
126 kafka.DefaultTopic(&kafka.Topic{Name: "Adapter"})); err != nil {
127 log.Errorw("fail-to-create-kafka-proxy", log.Fields{"error": err})
128 return
129 }
130 // Start the kafka messaging service - synchronous call to ensure
131 if err = core.kmp.Start(); err != nil {
132 log.Fatalw("error-starting-messaging-proxy", log.Fields{"error": err})
133 }
khenaidoocfee5f42018-07-19 22:47:38 -0400134}
135
khenaidoocfee5f42018-07-19 22:47:38 -0400136func (core *rwCore) stop() {
137 // Stop leadership tracking
138 core.halted = true
139
khenaidooabad44c2018-08-03 16:58:35 -0400140 // Stop the Kafka messaging service
141 if core.kmp != nil {
142 core.kmp.Stop()
143 }
144
khenaidoocfee5f42018-07-19 22:47:38 -0400145 // send exit signal
146 core.exitChannel <- 0
147
148 // Cleanup - applies only if we had a kvClient
149 if core.kvClient != nil {
150 // Release all reservations
151 if err := core.kvClient.ReleaseAllReservations(); err != nil {
khenaidoo5c11af72018-07-20 17:21:05 -0400152 log.Infow("fail-to-release-all-reservations", log.Fields{"error": err})
khenaidoocfee5f42018-07-19 22:47:38 -0400153 }
154 // Close the DB connection
155 core.kvClient.Close()
156 }
157}
158
159func waitForExit() int {
160 signalChannel := make(chan os.Signal, 1)
161 signal.Notify(signalChannel,
162 syscall.SIGHUP,
163 syscall.SIGINT,
164 syscall.SIGTERM,
165 syscall.SIGQUIT)
166
167 exitChannel := make(chan int)
168
169 go func() {
170 s := <-signalChannel
171 switch s {
172 case syscall.SIGHUP,
173 syscall.SIGINT,
174 syscall.SIGTERM,
175 syscall.SIGQUIT:
khenaidoo5c11af72018-07-20 17:21:05 -0400176 log.Infow("closing-signal-received", log.Fields{"signal": s})
khenaidoocfee5f42018-07-19 22:47:38 -0400177 exitChannel <- 0
178 default:
khenaidoo5c11af72018-07-20 17:21:05 -0400179 log.Infow("unexpected-signal-received", log.Fields{"signal": s})
khenaidoocfee5f42018-07-19 22:47:38 -0400180 exitChannel <- 1
181 }
182 }()
183
184 code := <-exitChannel
185 return code
186}
187
khenaidoo5c11af72018-07-20 17:21:05 -0400188func printBanner() {
189 fmt.Println(" ")
190 fmt.Println(" ______ ______ ")
191 fmt.Println("| _ \\ \\ / / ___|___ _ __ ___ ")
192 fmt.Println("| |_) \\ \\ /\\ / / | / _ \\| '__/ _ \\ ")
193 fmt.Println("| _ < \\ V V /| |__| (_) | | | __/ ")
194 fmt.Println("|_| \\_\\ \\_/\\_/ \\____\\___/|_| \\___| ")
195 fmt.Println(" ")
196}
197
khenaidoocfee5f42018-07-19 22:47:38 -0400198func main() {
199 start := time.Now()
200
201 cf := config.NewRWCoreFlags()
202 cf.ParseCommandArguments()
203
204 // Setup logging
khenaidoo5c11af72018-07-20 17:21:05 -0400205 if _, err := log.SetLogger(log.JSON, cf.LogLevel, log.Fields{"instanceId": cf.InstanceID}); err != nil {
khenaidoocfee5f42018-07-19 22:47:38 -0400206 log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
207 }
208 defer log.CleanUp()
209
khenaidoo5c11af72018-07-20 17:21:05 -0400210 // Print banner if specified
211 if cf.Banner {
212 printBanner()
213 }
214
215 log.Infow("rw-core-config", log.Fields{"config": *cf})
216
217 ctx, cancel := context.WithCancel(context.Background())
218 defer cancel()
khenaidoocfee5f42018-07-19 22:47:38 -0400219
220 core := newRWCore(cf)
khenaidoo5c11af72018-07-20 17:21:05 -0400221 go core.start(ctx)
khenaidoocfee5f42018-07-19 22:47:38 -0400222
223 code := waitForExit()
khenaidoo5c11af72018-07-20 17:21:05 -0400224 log.Infow("received-a-closing-signal", log.Fields{"code": code})
khenaidoocfee5f42018-07-19 22:47:38 -0400225
226 // Cleanup before leaving
227 core.stop()
228
229 elapsed := time.Since(start)
khenaidoo5c11af72018-07-20 17:21:05 -0400230 log.Infow("rw-core-run-time", log.Fields{"core": core.config.InstanceID, "time": elapsed / time.Second})
khenaidoocfee5f42018-07-19 22:47:38 -0400231}