2 Copyright (c) 2021 AT&T Intellectual Property.
3 Copyright (c) 2018-2021 Nokia.
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
9 http://www.apache.org/licenses/LICENSE-2.0
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.
19 * This source code is part of the near-RT RIC (RAN Intelligent Controller)
20 * platform project (RICP).
28 "github.com/go-redis/redis/v8"
32 type Sentinel struct {
38 type IredisSentinelClient interface {
39 Master(ctx context.Context, name string) *redis.StringStringMapCmd
40 Slaves(ctx context.Context, name string) *redis.SliceCmd
41 Sentinels(ctx context.Context, name string) *redis.SliceCmd
44 type RedisSentinelCreateCb func(cfg *Config, addr string) *Sentinel
46 func newRedisSentinel(cfg *Config, addr string) *Sentinel {
47 redisAddress := addr + ":" + cfg.sentinelPort
49 ctx: context.Background(),
50 IredisSentinelClient: redis.NewSentinelClient(&redis.Options{
52 Password: "", // no password set
53 DB: 0, // use default DB
61 func (s *Sentinel) GetDbState() (*DbState, error) {
63 pState, pErr := s.getPrimaryDbState()
64 rState, rErr := s.getReplicasState()
65 sState, sErr := s.getSentinelsState()
66 state.PrimaryDbState = *pState
67 state.ReplicasDbState = rState
68 state.SentinelsDbState = sState
70 cnt, err := strconv.Atoi(s.Cfg.nodeCnt)
72 state.Err = fmt.Errorf("Sentinel DBAAS_NODE_COUNT configuration value '%s' conversion to integer failed", s.Cfg.nodeCnt)
73 return state, state.Err
75 state.ConfigNodeCnt = cnt
86 func (s *Sentinel) getPrimaryDbState() (*PrimaryDbState, error) {
87 state := new(PrimaryDbState)
88 redisVal, redisErr := s.Master(s.ctx, s.Cfg.masterName).Result()
90 state.Fields.Ip = redisVal["ip"]
91 state.Fields.Port = redisVal["port"]
92 state.Fields.Flags = redisVal["flags"]
93 state.Fields.Role = redisVal["role-reported"]
96 return state, redisErr
99 func (s *Sentinel) getReplicasState() (*ReplicasDbState, error) {
100 states := new(ReplicasDbState)
101 states.States = make([]*ReplicaDbState, 0)
103 redisVal, redisErr := s.Slaves(s.ctx, s.Cfg.masterName).Result()
105 for _, redisReplica := range redisVal {
106 replicaState := readReplicaState(redisReplica.([]interface{}))
107 states.States = append(states.States, replicaState)
110 states.Err = redisErr
111 return states, redisErr
114 func readReplicaState(redisReplicas []interface{}) *ReplicaDbState {
115 state := new(ReplicaDbState)
116 for i := 0; i < len(redisReplicas); i += 2 {
117 if redisReplicas[i].(string) == "ip" {
118 state.Fields.Ip = redisReplicas[i+1].(string)
119 } else if redisReplicas[i].(string) == "port" {
120 state.Fields.Port = redisReplicas[i+1].(string)
121 } else if redisReplicas[i].(string) == "flags" {
122 state.Fields.Flags = redisReplicas[i+1].(string)
123 } else if redisReplicas[i].(string) == "role-reported" {
124 state.Fields.Role = redisReplicas[i+1].(string)
125 } else if redisReplicas[i].(string) == "master-link-status" {
126 state.Fields.PrimaryLinkStatus = redisReplicas[i+1].(string)
132 func (s *Sentinel) getSentinelsState() (*SentinelsDbState, error) {
133 states := new(SentinelsDbState)
134 states.States = make([]*SentinelDbState, 0)
136 redisVal, redisErr := s.Sentinels(s.ctx, s.Cfg.masterName).Result()
138 for _, redisSentinel := range redisVal {
139 sentinelState := readSentinelState(redisSentinel.([]interface{}))
140 // Ignore a sentinel entry with zero port, because missing of fix
141 // for the Redis Bug #9240.
142 if sentinelState.Fields.Port != "0" {
143 states.States = append(states.States, sentinelState)
147 states.Err = redisErr
148 return states, redisErr
151 func readSentinelState(redisSentinels []interface{}) *SentinelDbState {
152 state := new(SentinelDbState)
153 for i := 0; i < len(redisSentinels); i += 2 {
154 if redisSentinels[i].(string) == "ip" {
155 state.Fields.Ip = redisSentinels[i+1].(string)
156 } else if redisSentinels[i].(string) == "port" {
157 state.Fields.Port = redisSentinels[i+1].(string)
158 } else if redisSentinels[i].(string) == "flags" {
159 state.Fields.Flags = redisSentinels[i+1].(string)