blob: faa5851baf7d7fe6d89d0dbf1f1116974990f5b0 [file] [log] [blame]
khenaidoocfee5f42018-07-19 22:47:38 -04001package main
2
3import (
khenaidoo5c11af72018-07-20 17:21:05 -04004 "context"
5 "errors"
khenaidoocfee5f42018-07-19 22:47:38 -04006 "fmt"
khenaidoo5c11af72018-07-20 17:21:05 -04007 "github.com/opencord/voltha-go/common/log"
8 "github.com/opencord/voltha-go/db/kvstore"
9 "github.com/opencord/voltha-go/rw_core/config"
khenaidoocfee5f42018-07-19 22:47:38 -040010 "os"
11 "os/signal"
khenaidoocfee5f42018-07-19 22:47:38 -040012 "strconv"
khenaidoocfee5f42018-07-19 22:47:38 -040013 "syscall"
khenaidoo5c11af72018-07-20 17:21:05 -040014 "time"
khenaidoocfee5f42018-07-19 22:47:38 -040015)
16
17type rwCore struct {
khenaidoo5c11af72018-07-20 17:21:05 -040018 kvClient kvstore.Client
19 config *config.RWCoreFlags
20 halted bool
21 exitChannel chan int
khenaidoocfee5f42018-07-19 22:47:38 -040022}
23
24func newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
25
khenaidoo5c11af72018-07-20 17:21:05 -040026 log.Infow("kv-store-type", log.Fields{"store": storeType})
khenaidoocfee5f42018-07-19 22:47:38 -040027 switch storeType {
28 case "consul":
29 return kvstore.NewConsulClient(address, timeout)
30 case "etcd":
31 return kvstore.NewEtcdClient(address, timeout)
32 }
33 return nil, errors.New("unsupported-kv-store")
34}
35
36func newRWCore(cf *config.RWCoreFlags) *rwCore {
37 var rwCore rwCore
38 rwCore.config = cf
39 rwCore.halted = false
40 rwCore.exitChannel = make(chan int, 1)
41 return &rwCore
42}
43
44func (core *rwCore) setKVClient() error {
45 addr := core.config.KVStoreHost + ":" + strconv.Itoa(core.config.KVStorePort)
46 client, err := newKVClient(core.config.KVStoreType, addr, core.config.KVStoreTimeout)
47 if err != nil {
48 log.Error(err)
49 return err
50 }
51 core.kvClient = client
52 return nil
53}
54
khenaidoocfee5f42018-07-19 22:47:38 -040055func toString(value interface{}) (string, error) {
56 switch t := value.(type) {
57 case []byte:
58 return string(value.([]byte)), nil
59 case string:
60 return value.(string), nil
61 default:
62 return "", fmt.Errorf("unexpected-type-%T", t)
63 }
64}
65
khenaidoo5c11af72018-07-20 17:21:05 -040066func (core *rwCore) start(ctx context.Context) {
67 log.Info("Starting RW Core components")
68 // Setup GRPC Server
khenaidoocfee5f42018-07-19 22:47:38 -040069
khenaidoo5c11af72018-07-20 17:21:05 -040070 // Setup KV Client
khenaidoocfee5f42018-07-19 22:47:38 -040071
khenaidoo5c11af72018-07-20 17:21:05 -040072 // Setup Kafka messaging services
73
khenaidoocfee5f42018-07-19 22:47:38 -040074}
75
khenaidoocfee5f42018-07-19 22:47:38 -040076func (core *rwCore) stop() {
77 // Stop leadership tracking
78 core.halted = true
79
80 // send exit signal
81 core.exitChannel <- 0
82
83 // Cleanup - applies only if we had a kvClient
84 if core.kvClient != nil {
85 // Release all reservations
86 if err := core.kvClient.ReleaseAllReservations(); err != nil {
khenaidoo5c11af72018-07-20 17:21:05 -040087 log.Infow("fail-to-release-all-reservations", log.Fields{"error": err})
khenaidoocfee5f42018-07-19 22:47:38 -040088 }
89 // Close the DB connection
90 core.kvClient.Close()
91 }
92}
93
94func waitForExit() int {
95 signalChannel := make(chan os.Signal, 1)
96 signal.Notify(signalChannel,
97 syscall.SIGHUP,
98 syscall.SIGINT,
99 syscall.SIGTERM,
100 syscall.SIGQUIT)
101
102 exitChannel := make(chan int)
103
104 go func() {
105 s := <-signalChannel
106 switch s {
107 case syscall.SIGHUP,
108 syscall.SIGINT,
109 syscall.SIGTERM,
110 syscall.SIGQUIT:
khenaidoo5c11af72018-07-20 17:21:05 -0400111 log.Infow("closing-signal-received", log.Fields{"signal": s})
khenaidoocfee5f42018-07-19 22:47:38 -0400112 exitChannel <- 0
113 default:
khenaidoo5c11af72018-07-20 17:21:05 -0400114 log.Infow("unexpected-signal-received", log.Fields{"signal": s})
khenaidoocfee5f42018-07-19 22:47:38 -0400115 exitChannel <- 1
116 }
117 }()
118
119 code := <-exitChannel
120 return code
121}
122
khenaidoo5c11af72018-07-20 17:21:05 -0400123func printBanner() {
124 fmt.Println(" ")
125 fmt.Println(" ______ ______ ")
126 fmt.Println("| _ \\ \\ / / ___|___ _ __ ___ ")
127 fmt.Println("| |_) \\ \\ /\\ / / | / _ \\| '__/ _ \\ ")
128 fmt.Println("| _ < \\ V V /| |__| (_) | | | __/ ")
129 fmt.Println("|_| \\_\\ \\_/\\_/ \\____\\___/|_| \\___| ")
130 fmt.Println(" ")
131}
132
khenaidoocfee5f42018-07-19 22:47:38 -0400133func main() {
134 start := time.Now()
135
136 cf := config.NewRWCoreFlags()
137 cf.ParseCommandArguments()
138
139 // Setup logging
khenaidoo5c11af72018-07-20 17:21:05 -0400140 if _, err := log.SetLogger(log.JSON, cf.LogLevel, log.Fields{"instanceId": cf.InstanceID}); err != nil {
khenaidoocfee5f42018-07-19 22:47:38 -0400141 log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
142 }
143 defer log.CleanUp()
144
khenaidoo5c11af72018-07-20 17:21:05 -0400145 // Print banner if specified
146 if cf.Banner {
147 printBanner()
148 }
149
150 log.Infow("rw-core-config", log.Fields{"config": *cf})
151
152 ctx, cancel := context.WithCancel(context.Background())
153 defer cancel()
khenaidoocfee5f42018-07-19 22:47:38 -0400154
155 core := newRWCore(cf)
khenaidoo5c11af72018-07-20 17:21:05 -0400156 go core.start(ctx)
khenaidoocfee5f42018-07-19 22:47:38 -0400157
158 code := waitForExit()
khenaidoo5c11af72018-07-20 17:21:05 -0400159 log.Infow("received-a-closing-signal", log.Fields{"code": code})
khenaidoocfee5f42018-07-19 22:47:38 -0400160
161 // Cleanup before leaving
162 core.stop()
163
164 elapsed := time.Since(start)
khenaidoo5c11af72018-07-20 17:21:05 -0400165 log.Infow("rw-core-run-time", log.Fields{"core": core.config.InstanceID, "time": elapsed / time.Second})
khenaidoocfee5f42018-07-19 22:47:38 -0400166}