2 Copyright (c) 2021 AT&T Intellectual Property.
3 Copyright (c) 2018-2022 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 {
39 type IredisSentinelClient interface {
40 Master(ctx context.Context, name string) *redis.StringStringMapCmd
41 Slaves(ctx context.Context, name string) *redis.SliceCmd
42 Sentinels(ctx context.Context, name string) *redis.SliceCmd
45 type RedisSentinelCreateCb func(addr, sentinelPort, masterName, nodeCnt string) *Sentinel
47 func newRedisSentinel(addr, sentinelPort, masterName, nodeCnt string) *Sentinel {
48 redisAddress := addr + ":" + sentinelPort
50 ctx: context.Background(),
51 IredisSentinelClient: redis.NewSentinelClient(&redis.Options{
53 Password: "", // no password set
54 DB: 0, // use default DB
58 MasterName: masterName,
63 func (s *Sentinel) GetDbState() (*DbState, error) {
65 pState, pErr := s.getPrimaryDbState()
66 rState, rErr := s.getReplicasState()
67 sState, sErr := s.getSentinelsState()
68 state.PrimaryDbState = *pState
69 state.ReplicasDbState = rState
70 state.SentinelsDbState = sState
72 cnt, err := strconv.Atoi(s.NodeCnt)
74 state.Err = fmt.Errorf("Sentinel DBAAS_NODE_COUNT configuration value '%s' conversion to integer failed", s.NodeCnt)
75 return state, state.Err
77 state.ConfigNodeCnt = cnt
88 func (s *Sentinel) getPrimaryDbState() (*PrimaryDbState, error) {
89 state := new(PrimaryDbState)
90 redisVal, redisErr := s.Master(s.ctx, s.MasterName).Result()
92 state.Fields.Ip = redisVal["ip"]
93 state.Fields.Port = redisVal["port"]
94 state.Fields.Flags = redisVal["flags"]
95 state.Fields.Role = redisVal["role-reported"]
98 return state, redisErr
101 func (s *Sentinel) getReplicasState() (*ReplicasDbState, error) {
102 states := new(ReplicasDbState)
103 states.States = make([]*ReplicaDbState, 0)
105 redisVal, redisErr := s.Slaves(s.ctx, s.MasterName).Result()
107 for _, redisReplica := range redisVal {
108 replicaState := readReplicaState(redisReplica.([]interface{}))
109 states.States = append(states.States, replicaState)
112 states.Err = redisErr
113 return states, redisErr
116 func readReplicaState(redisReplicas []interface{}) *ReplicaDbState {
117 state := new(ReplicaDbState)
118 for i := 0; i < len(redisReplicas); i += 2 {
119 if redisReplicas[i].(string) == "ip" {
120 state.Fields.Ip = redisReplicas[i+1].(string)
121 } else if redisReplicas[i].(string) == "port" {
122 state.Fields.Port = redisReplicas[i+1].(string)
123 } else if redisReplicas[i].(string) == "flags" {
124 state.Fields.Flags = redisReplicas[i+1].(string)
125 } else if redisReplicas[i].(string) == "role-reported" {
126 state.Fields.Role = redisReplicas[i+1].(string)
127 } else if redisReplicas[i].(string) == "master-link-status" {
128 state.Fields.PrimaryLinkStatus = redisReplicas[i+1].(string)
134 func (s *Sentinel) getSentinelsState() (*SentinelsDbState, error) {
135 states := new(SentinelsDbState)
136 states.States = make([]*SentinelDbState, 0)
138 redisVal, redisErr := s.Sentinels(s.ctx, s.MasterName).Result()
140 for _, redisSentinel := range redisVal {
141 sentinelState := readSentinelState(redisSentinel.([]interface{}))
142 // Ignore a sentinel entry with zero port, because missing of fix
143 // for the Redis Bug #9240.
144 if sentinelState.Fields.Port != "0" {
145 states.States = append(states.States, sentinelState)
149 states.Err = redisErr
150 return states, redisErr
153 func readSentinelState(redisSentinels []interface{}) *SentinelDbState {
154 state := new(SentinelDbState)
155 for i := 0; i < len(redisSentinels); i += 2 {
156 if redisSentinels[i].(string) == "ip" {
157 state.Fields.Ip = redisSentinels[i+1].(string)
158 } else if redisSentinels[i].(string) == "port" {
159 state.Fields.Port = redisSentinels[i+1].(string)
160 } else if redisSentinels[i].(string) == "flags" {
161 state.Fields.Flags = redisSentinels[i+1].(string)