Fix sdlcli healthcheck DBAAS status in SEP install
[ric-plt/sdlgo.git] / internal / sdlgoredis / sdlgosentinel.go
1 /*
2    Copyright (c) 2021 AT&T Intellectual Property.
3    Copyright (c) 2018-2021 Nokia.
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16 */
17
18 /*
19  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
20  * platform project (RICP).
21  */
22
23 package sdlgoredis
24
25 import (
26         "fmt"
27         "github.com/go-redis/redis/v7"
28         "strconv"
29 )
30
31 type Sentinel struct {
32         IredisSentinelClient
33         Cfg *Config
34 }
35
36 type IredisSentinelClient interface {
37         Master(name string) *redis.StringStringMapCmd
38         Slaves(name string) *redis.SliceCmd
39         Sentinels(name string) *redis.SliceCmd
40 }
41
42 type RedisSentinelCreateCb func(cfg *Config, addr string) *Sentinel
43
44 func newRedisSentinel(cfg *Config, addr string) *Sentinel {
45         redisAddress := addr + ":" + cfg.sentinelPort
46         return &Sentinel{
47                 IredisSentinelClient: redis.NewSentinelClient(&redis.Options{
48                         Addr:       redisAddress,
49                         Password:   "", // no password set
50                         DB:         0,  // use default DB
51                         PoolSize:   20,
52                         MaxRetries: 2,
53                 }),
54                 Cfg: cfg,
55         }
56 }
57
58 func (s *Sentinel) GetDbState() (*DbState, error) {
59         state := new(DbState)
60         pState, pErr := s.getPrimaryDbState()
61         rState, rErr := s.getReplicasState()
62         sState, sErr := s.getSentinelsState()
63         state.PrimaryDbState = *pState
64         state.ReplicasDbState = rState
65         state.SentinelsDbState = sState
66
67         cnt, err := strconv.Atoi(s.Cfg.nodeCnt)
68         if err != nil {
69                 state.Err = fmt.Errorf("Sentinel DBAAS_NODE_COUNT configuration value '%s' conversion to integer failed", s.Cfg.nodeCnt)
70                 return state, state.Err
71         }
72         state.ConfigNodeCnt = cnt
73
74         if pErr != nil {
75                 return state, pErr
76         }
77         if rErr != nil {
78                 return state, rErr
79         }
80         return state, sErr
81 }
82
83 func (s *Sentinel) getPrimaryDbState() (*PrimaryDbState, error) {
84         state := new(PrimaryDbState)
85         redisVal, redisErr := s.Master(s.Cfg.masterName).Result()
86         if redisErr == nil {
87                 state.Fields.Ip = redisVal["ip"]
88                 state.Fields.Port = redisVal["port"]
89                 state.Fields.Flags = redisVal["flags"]
90                 state.Fields.Role = redisVal["role-reported"]
91         }
92         state.Err = redisErr
93         return state, redisErr
94 }
95
96 func (s *Sentinel) getReplicasState() (*ReplicasDbState, error) {
97         states := new(ReplicasDbState)
98         states.States = make([]*ReplicaDbState, 0)
99
100         redisVal, redisErr := s.Slaves(s.Cfg.masterName).Result()
101         if redisErr == nil {
102                 for _, redisReplica := range redisVal {
103                         replicaState := readReplicaState(redisReplica.([]interface{}))
104                         states.States = append(states.States, replicaState)
105                 }
106         }
107         states.Err = redisErr
108         return states, redisErr
109 }
110
111 func readReplicaState(redisReplicas []interface{}) *ReplicaDbState {
112         state := new(ReplicaDbState)
113         for i := 0; i < len(redisReplicas); i += 2 {
114                 if redisReplicas[i].(string) == "ip" {
115                         state.Fields.Ip = redisReplicas[i+1].(string)
116                 } else if redisReplicas[i].(string) == "port" {
117                         state.Fields.Port = redisReplicas[i+1].(string)
118                 } else if redisReplicas[i].(string) == "flags" {
119                         state.Fields.Flags = redisReplicas[i+1].(string)
120                 } else if redisReplicas[i].(string) == "role-reported" {
121                         state.Fields.Role = redisReplicas[i+1].(string)
122                 } else if redisReplicas[i].(string) == "master-link-status" {
123                         state.Fields.PrimaryLinkStatus = redisReplicas[i+1].(string)
124                 }
125         }
126         return state
127 }
128
129 func (s *Sentinel) getSentinelsState() (*SentinelsDbState, error) {
130         states := new(SentinelsDbState)
131         states.States = make([]*SentinelDbState, 0)
132
133         redisVal, redisErr := s.Sentinels(s.Cfg.masterName).Result()
134         if redisErr == nil {
135                 for _, redisSentinel := range redisVal {
136                         sentinelState := readSentinelState(redisSentinel.([]interface{}))
137                         states.States = append(states.States, sentinelState)
138                 }
139         }
140         states.Err = redisErr
141         return states, redisErr
142 }
143
144 func readSentinelState(redisSentinels []interface{}) *SentinelDbState {
145         state := new(SentinelDbState)
146         for i := 0; i < len(redisSentinels); i += 2 {
147                 if redisSentinels[i].(string) == "ip" {
148                         state.Fields.Ip = redisSentinels[i+1].(string)
149                 } else if redisSentinels[i].(string) == "port" {
150                         state.Fields.Port = redisSentinels[i+1].(string)
151                 } else if redisSentinels[i].(string) == "flags" {
152                         state.Fields.Flags = redisSentinels[i+1].(string)
153                 }
154         }
155         return state
156 }