f4395700d1e6e5799ba0ad17afcb7b6965e2cd40
[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         "github.com/go-redis/redis/v7"
27 )
28
29 type Sentinel struct {
30         IredisSentinelClient
31         Cfg *Config
32 }
33
34 type IredisSentinelClient interface {
35         Master(name string) *redis.StringStringMapCmd
36         Slaves(name string) *redis.SliceCmd
37         Sentinels(name string) *redis.SliceCmd
38 }
39
40 type RedisSentinelCreateCb func(cfg *Config, addr string) *Sentinel
41
42 func newRedisSentinel(cfg *Config, addr string) *Sentinel {
43         redisAddress := addr + ":" + cfg.sentinelPort
44         return &Sentinel{
45                 IredisSentinelClient: redis.NewSentinelClient(&redis.Options{
46                         Addr:       redisAddress,
47                         Password:   "", // no password set
48                         DB:         0,  // use default DB
49                         PoolSize:   20,
50                         MaxRetries: 2,
51                 }),
52                 Cfg: cfg,
53         }
54 }
55
56 func (s *Sentinel) GetDbState() (*DbState, error) {
57         state := new(DbState)
58         pState, pErr := s.getPrimaryDbState()
59         rState, rErr := s.getReplicasState()
60         sState, sErr := s.getSentinelsState()
61         state.PrimaryDbState = *pState
62         state.ReplicasDbState = rState
63         state.SentinelsDbState = sState
64         if pErr != nil {
65                 return state, pErr
66         }
67         if rErr != nil {
68                 return state, rErr
69         }
70         return state, sErr
71 }
72
73 func (s *Sentinel) getPrimaryDbState() (*PrimaryDbState, error) {
74         state := new(PrimaryDbState)
75         redisVal, redisErr := s.Master(s.Cfg.masterName).Result()
76         if redisErr == nil {
77                 state.Fields.Ip = redisVal["ip"]
78                 state.Fields.Port = redisVal["port"]
79                 state.Fields.Flags = redisVal["flags"]
80                 state.Fields.Role = redisVal["role-reported"]
81         }
82         state.Err = redisErr
83         return state, redisErr
84 }
85
86 func (s *Sentinel) getReplicasState() (*ReplicasDbState, error) {
87         states := new(ReplicasDbState)
88         states.States = make([]*ReplicaDbState, 0)
89
90         redisVal, redisErr := s.Slaves(s.Cfg.masterName).Result()
91         if redisErr == nil {
92                 for _, redisReplica := range redisVal {
93                         replicaState := readReplicaState(redisReplica.([]interface{}))
94                         states.States = append(states.States, replicaState)
95                 }
96         }
97         states.Err = redisErr
98         return states, redisErr
99 }
100
101 func readReplicaState(redisReplicas []interface{}) *ReplicaDbState {
102         state := new(ReplicaDbState)
103         for i := 0; i < len(redisReplicas); i += 2 {
104                 if redisReplicas[i].(string) == "ip" {
105                         state.Fields.Ip = redisReplicas[i+1].(string)
106                 } else if redisReplicas[i].(string) == "port" {
107                         state.Fields.Port = redisReplicas[i+1].(string)
108                 } else if redisReplicas[i].(string) == "flags" {
109                         state.Fields.Flags = redisReplicas[i+1].(string)
110                 } else if redisReplicas[i].(string) == "role-reported" {
111                         state.Fields.Role = redisReplicas[i+1].(string)
112                 } else if redisReplicas[i].(string) == "master-link-status" {
113                         state.Fields.PrimaryLinkStatus = redisReplicas[i+1].(string)
114                 }
115         }
116         return state
117 }
118
119 func (s *Sentinel) getSentinelsState() (*SentinelsDbState, error) {
120         states := new(SentinelsDbState)
121         states.States = make([]*SentinelDbState, 0)
122
123         redisVal, redisErr := s.Sentinels(s.Cfg.masterName).Result()
124         if redisErr == nil {
125                 for _, redisSentinel := range redisVal {
126                         sentinelState := readSentinelState(redisSentinel.([]interface{}))
127                         states.States = append(states.States, sentinelState)
128                 }
129         }
130         states.Err = redisErr
131         return states, redisErr
132 }
133
134 func readSentinelState(redisSentinels []interface{}) *SentinelDbState {
135         state := new(SentinelDbState)
136         for i := 0; i < len(redisSentinels); i += 2 {
137                 if redisSentinels[i].(string) == "ip" {
138                         state.Fields.Ip = redisSentinels[i+1].(string)
139                 } else if redisSentinels[i].(string) == "port" {
140                         state.Fields.Port = redisSentinels[i+1].(string)
141                 } else if redisSentinels[i].(string) == "flags" {
142                         state.Fields.Flags = redisSentinels[i+1].(string)
143                 }
144         }
145         return state
146 }