RLTest 0.7.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- RLTest/Enterprise/CcsMock.py +183 -0
- RLTest/Enterprise/Dmc.py +47 -0
- RLTest/Enterprise/EnterpriseClusterEnv.py +158 -0
- RLTest/Enterprise/__init__.py +5 -0
- RLTest/Enterprise/binaryrepo.py +71 -0
- RLTest/__init__.py +10 -0
- RLTest/__main__.py +1026 -0
- RLTest/_version.py +8 -0
- RLTest/debuggers.py +81 -0
- RLTest/env.py +646 -0
- RLTest/exists_redis.py +122 -0
- RLTest/loader.py +174 -0
- RLTest/random_port.py +63 -0
- RLTest/redis_cluster.py +241 -0
- RLTest/redis_enterprise_cluster.py +127 -0
- RLTest/redis_std.py +649 -0
- RLTest/utils.py +181 -0
- rltest-0.7.14.dist-info/LICENSE +29 -0
- rltest-0.7.14.dist-info/METADATA +296 -0
- rltest-0.7.14.dist-info/RECORD +22 -0
- rltest-0.7.14.dist-info/WHEEL +4 -0
- rltest-0.7.14.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
import subprocess
|
|
3
|
+
import redis
|
|
4
|
+
import os
|
|
5
|
+
from RLTest.utils import wait_for_conn, Colors
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CcsMock():
|
|
9
|
+
CCS_UNIX_SOCKET_DEFAULT_PATH = '/tmp/ccs.sock'
|
|
10
|
+
CCS_DB_RDB_FILE_NAME = 'syncer-pixie-ccs.rdb'
|
|
11
|
+
CCS_LOG_FILE_NAME = 'ccs.log'
|
|
12
|
+
|
|
13
|
+
def __init__(self, redisBinaryPath, proxyPort, directory=None, useSlaves=False, password=None, libPath=None):
|
|
14
|
+
self.redisBinaryPath = os.path.expanduser(redisBinaryPath) if redisBinaryPath.startswith('~/') else redisBinaryPath
|
|
15
|
+
self.useSlaves = useSlaves
|
|
16
|
+
self.directory = directory
|
|
17
|
+
self.generateArgs()
|
|
18
|
+
self.libPath = os.path.expanduser(libPath) if libPath.startswith('~/') else libPath
|
|
19
|
+
self.env = {}
|
|
20
|
+
if self.libPath:
|
|
21
|
+
self.env['LD_LIBRARY_PATH'] = self.libPath
|
|
22
|
+
self.password = password
|
|
23
|
+
self.proxyPort = proxyPort
|
|
24
|
+
|
|
25
|
+
def generateArgs(self):
|
|
26
|
+
self.args = self.redisBinaryPath.split()
|
|
27
|
+
if self.directory:
|
|
28
|
+
self.args += ['--dir', self.directory]
|
|
29
|
+
self.args += ['--port', '0',
|
|
30
|
+
'--unixsocket', self.CCS_UNIX_SOCKET_DEFAULT_PATH,
|
|
31
|
+
'--dbfilename', self.CCS_DB_RDB_FILE_NAME,
|
|
32
|
+
'--logfile', self.CCS_LOG_FILE_NAME]
|
|
33
|
+
|
|
34
|
+
def Start(self, shards, bdb_fields=None, endpoint_ccs_params=None, legacy_hash_slots=True, extra_keys=None):
|
|
35
|
+
self.setup(shards, bdb_fields, endpoint_ccs_params, legacy_hash_slots, extra_keys)
|
|
36
|
+
|
|
37
|
+
def Stop(self):
|
|
38
|
+
if self.process:
|
|
39
|
+
try:
|
|
40
|
+
self.process.terminate()
|
|
41
|
+
self.process.wait()
|
|
42
|
+
except OSError:
|
|
43
|
+
pass
|
|
44
|
+
self.process = None
|
|
45
|
+
|
|
46
|
+
def PrintEnvData(self, prefix=''):
|
|
47
|
+
print(Colors.Yellow(prefix + 'pid: %d' % self.process.pid))
|
|
48
|
+
print(Colors.Yellow(prefix + 'unix socket: %s' % self.CCS_UNIX_SOCKET_DEFAULT_PATH))
|
|
49
|
+
print(Colors.Yellow(prefix + 'binary path: %s' % self.redisBinaryPath))
|
|
50
|
+
if self.directory:
|
|
51
|
+
print(Colors.Yellow(prefix + 'db dir path: %s' % (self.directory)))
|
|
52
|
+
print(Colors.Yellow(prefix + 'rdb file name: %s' % (self.CCS_DB_RDB_FILE_NAME)))
|
|
53
|
+
print(Colors.Yellow(prefix + 'log file name: %s' % (self.CCS_LOG_FILE_NAME)))
|
|
54
|
+
if self.libPath:
|
|
55
|
+
print(Colors.Yellow(prefix + 'lib path: %s' % (self.libPath)))
|
|
56
|
+
|
|
57
|
+
def setup(self, shards, bdb_fields=None, endpoint_ccs_params=None, legacy_hash_slots=True, extra_keys=None):
|
|
58
|
+
|
|
59
|
+
self.process = subprocess.Popen(stdout=subprocess.PIPE, stderr=subprocess.STDOUT, args=self.args, env=self.env)
|
|
60
|
+
|
|
61
|
+
# Create fake cluster, node and dmc objects
|
|
62
|
+
self.conn = redis.Redis(unix_socket_path=self.CCS_UNIX_SOCKET_DEFAULT_PATH)
|
|
63
|
+
wait_for_conn(self.conn)
|
|
64
|
+
|
|
65
|
+
self.conn.hmset('cluster', {'name': 'fakecluster'})
|
|
66
|
+
self.conn.hmset('node:1', {'addr': '127.0.0.1',
|
|
67
|
+
'dmc_uid': '1'})
|
|
68
|
+
self.conn.sadd('node:all', '1')
|
|
69
|
+
self.conn.hmset('dmc:1', {'threads': '1',
|
|
70
|
+
'max_threads': '1',
|
|
71
|
+
'log_level': 'info'})
|
|
72
|
+
self.conn.sadd('dmc:all', '1')
|
|
73
|
+
# self.conn.hmset('cluster_cert', {"syncer_cert": "syncer_cert", "syncer_key": "syncer_key"}) todo: check if needed
|
|
74
|
+
self.disperse_shards = False
|
|
75
|
+
self.next_node_uid = 1
|
|
76
|
+
|
|
77
|
+
self.create_bdb(shards, bdb_fields, endpoint_ccs_params, legacy_hash_slots, extra_keys)
|
|
78
|
+
|
|
79
|
+
def set_server_ccs_values(self, serverId, port, assigned_slots, bdb_uid, role):
|
|
80
|
+
"""
|
|
81
|
+
Set all the neccesary values of a server in the ccs
|
|
82
|
+
"""
|
|
83
|
+
redis_uid = serverId
|
|
84
|
+
self.conn.hmset('redis:%s' % str(redis_uid),
|
|
85
|
+
{'port': port,
|
|
86
|
+
'node_uid': str(self.next_node_uid),
|
|
87
|
+
'bdb_uid': bdb_uid,
|
|
88
|
+
'role': role,
|
|
89
|
+
'assigned_slots': assigned_slots})
|
|
90
|
+
self.conn.sadd('redis:all', redis_uid)
|
|
91
|
+
# we promote the node uid just in case of master shard because we want disperion of master shards
|
|
92
|
+
if role == 'master' and self.disperse_shards:
|
|
93
|
+
n_nodes = len(self.conn.smembers('node:all'))
|
|
94
|
+
self.next_node_uid = self.next_node_uid % n_nodes + 1
|
|
95
|
+
|
|
96
|
+
def update_bdb_redis_list(self, bdb_uid, shards):
|
|
97
|
+
"""
|
|
98
|
+
Update the redis list in the ccs of the given bdb
|
|
99
|
+
"""
|
|
100
|
+
bdb_uid = str(bdb_uid)
|
|
101
|
+
redis_uids = []
|
|
102
|
+
for shard in shards:
|
|
103
|
+
redis_uids.append(str(shard.masterServerId))
|
|
104
|
+
if self.useSlaves:
|
|
105
|
+
redis_uids.append(str(shard.slaveServerId))
|
|
106
|
+
self.conn.hset('bdb:%s' % bdb_uid, 'redis_list', ','.join(redis_uids))
|
|
107
|
+
|
|
108
|
+
def create_bdb(self, shards, bdb_fields=None, endpoint_ccs_params=None, legacy_hash_slots=True, extra_keys=None):
|
|
109
|
+
bdb_uid = 1
|
|
110
|
+
port = self.proxyPort
|
|
111
|
+
|
|
112
|
+
if legacy_hash_slots:
|
|
113
|
+
number_of_slots_in_bdb = 4096
|
|
114
|
+
translation_offset = 1
|
|
115
|
+
else:
|
|
116
|
+
number_of_slots_in_bdb = 16384
|
|
117
|
+
translation_offset = 0
|
|
118
|
+
slots_per_shard = float(number_of_slots_in_bdb) / len(shards)
|
|
119
|
+
first_slot = translation_offset
|
|
120
|
+
last_slot = number_of_slots_in_bdb - 1 + translation_offset
|
|
121
|
+
|
|
122
|
+
start_slots = [int(round(first_slot + i * slots_per_shard)) for i in range(len(shards))]
|
|
123
|
+
end_slots = [next_start_slot - 1 for next_start_slot in start_slots[1:]] + [last_slot]
|
|
124
|
+
slots = ["%s-%s" % (pair[0], pair[1]) for pair in zip(start_slots, end_slots)]
|
|
125
|
+
|
|
126
|
+
for index, shard in enumerate(shards):
|
|
127
|
+
self.set_server_ccs_values(shard.masterServerId, shard.port, str(slots[index]), bdb_uid, 'master')
|
|
128
|
+
|
|
129
|
+
if self.useSlaves:
|
|
130
|
+
self.set_server_ccs_values(shard.slaveServerId, shard.GetSlavePort(), str(slots[index]), bdb_uid, 'slave')
|
|
131
|
+
|
|
132
|
+
self.conn.hmset('bdb:%s' % bdb_uid,
|
|
133
|
+
{'shards_count': len(shards),
|
|
134
|
+
'type': 'redis',
|
|
135
|
+
'endpoint_list': '%s:1' % bdb_uid,
|
|
136
|
+
'replication': ('enabled' if self.useSlaves else 'disabled'),
|
|
137
|
+
'authentication_admin_pass': 'secret',
|
|
138
|
+
'internal_pass': self.password,
|
|
139
|
+
'redis_version': '4.0',
|
|
140
|
+
'implicit_shard_key': 'enabled'})
|
|
141
|
+
|
|
142
|
+
if legacy_hash_slots:
|
|
143
|
+
self.conn.hmset('bdb:%s' % bdb_uid,
|
|
144
|
+
{'hash_slots_policy': 'legacy',
|
|
145
|
+
'shard_function': 'crc12'})
|
|
146
|
+
else:
|
|
147
|
+
self.conn.hmset('bdb:%s' % bdb_uid,
|
|
148
|
+
{'hash_slots_policy': '16k'})
|
|
149
|
+
|
|
150
|
+
if bdb_fields:
|
|
151
|
+
self.conn.hmset('bdb:%s' % bdb_uid, bdb_fields)
|
|
152
|
+
# if 'ssl' in bdb_fields and bdb_fields['ssl'] in ["enabled", "replica_ssl"]:
|
|
153
|
+
# with open(CLIENT_CERT_FILE, 'r') as cert_file:
|
|
154
|
+
# cert = cert_file.readlines()
|
|
155
|
+
# self.conn.hmset('bdb:%s' % bdb_uid,
|
|
156
|
+
# {'authentication_ssl_client_certs': "".join(cert)})
|
|
157
|
+
|
|
158
|
+
if extra_keys:
|
|
159
|
+
for key, val in extra_keys.items():
|
|
160
|
+
self.conn.hmset(key, val)
|
|
161
|
+
|
|
162
|
+
# Set up endpoint
|
|
163
|
+
proxy_policy = self.conn.hget('bdb:%s' % bdb_uid, 'proxy_policy')
|
|
164
|
+
if not proxy_policy:
|
|
165
|
+
proxy_policy = 'all-nodes'
|
|
166
|
+
|
|
167
|
+
self.conn.hmset('endpoint:%s:1' % bdb_uid,
|
|
168
|
+
{'bdb_uid': bdb_uid,
|
|
169
|
+
'port': port,
|
|
170
|
+
'proxy_policy': proxy_policy})
|
|
171
|
+
self.conn.hmset('endpoint:%s:1' % bdb_uid,
|
|
172
|
+
{'bdb_uid': bdb_uid,
|
|
173
|
+
'port': port,
|
|
174
|
+
'proxy_policy': proxy_policy,
|
|
175
|
+
'proxy_uids': '1'})
|
|
176
|
+
|
|
177
|
+
if endpoint_ccs_params:
|
|
178
|
+
self.conn.hmset('endpoint:%s:1' % bdb_uid, endpoint_ccs_params)
|
|
179
|
+
|
|
180
|
+
self.conn.sadd('endpoint:all', '%s:1' % bdb_uid)
|
|
181
|
+
|
|
182
|
+
self.conn.sadd('bdb:all', bdb_uid)
|
|
183
|
+
self.update_bdb_redis_list(bdb_uid, shards)
|
RLTest/Enterprise/Dmc.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import psutil
|
|
5
|
+
import subprocess
|
|
6
|
+
from RLTest.utils import Colors
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Dmc():
|
|
10
|
+
DMC_LOG_FILE_NAME = 'dmc.log'
|
|
11
|
+
|
|
12
|
+
def __init__(self, dmcBinaryPath, libPath, directory=None):
|
|
13
|
+
self.dmcBinaryPath = os.path.expanduser(dmcBinaryPath) if dmcBinaryPath.startswith('~/') else dmcBinaryPath
|
|
14
|
+
self.env = {'MEMTIER_NODE_ID': '1'}
|
|
15
|
+
self.libPath = libPath
|
|
16
|
+
if 'LD_LIBRARY_PATH' in os.environ:
|
|
17
|
+
self.env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
|
|
18
|
+
else:
|
|
19
|
+
self.env['LD_LIBRARY_PATH'] = os.path.expanduser(self.libPath) if dmcBinaryPath.startswith('~/') else self.libPath
|
|
20
|
+
self.directory = directory
|
|
21
|
+
|
|
22
|
+
logFile = self.DMC_LOG_FILE_NAME if self.directory is None else os.path.join(self.directory, self.DMC_LOG_FILE_NAME)
|
|
23
|
+
self.proxyArgs = [
|
|
24
|
+
self.dmcBinaryPath,
|
|
25
|
+
'-c', '500',
|
|
26
|
+
'-O', logFile
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
def Start(self):
|
|
30
|
+
self.process = psutil.Popen(executable=self.dmcBinaryPath,
|
|
31
|
+
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
|
|
32
|
+
env=self.env,
|
|
33
|
+
args=self.proxyArgs)
|
|
34
|
+
|
|
35
|
+
def Stop(self):
|
|
36
|
+
if self.process:
|
|
37
|
+
self.process.kill()
|
|
38
|
+
self.process.wait()
|
|
39
|
+
self.process = None
|
|
40
|
+
|
|
41
|
+
def PrintEnvData(self, prefix=''):
|
|
42
|
+
print(Colors.Yellow(prefix + 'dmc binary path: %s' % self.dmcBinaryPath))
|
|
43
|
+
print(Colors.Yellow(prefix + 'dmc env: %s' % str(self.env)))
|
|
44
|
+
print(Colors.Yellow(prefix + 'dir path: %s' % str(self.directory)))
|
|
45
|
+
print(Colors.Yellow(prefix + 'log file name: %s' % str(self.DMC_LOG_FILE_NAME)))
|
|
46
|
+
if self.libPath:
|
|
47
|
+
print(Colors.Yellow(prefix + 'lib path: %s' % str(self.libPath)))
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
|
|
3
|
+
from RLTest.redis_std import StandardEnv
|
|
4
|
+
from RLTest.utils import Colors, wait_for_conn
|
|
5
|
+
from .CcsMock import CcsMock
|
|
6
|
+
from .Dmc import Dmc
|
|
7
|
+
import redis
|
|
8
|
+
import os
|
|
9
|
+
import json
|
|
10
|
+
from zipfile import ZipFile
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
SHARD_PASSWORD = 'password'
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class EnterpriseClusterEnv():
|
|
17
|
+
DMC_PORT = 10000
|
|
18
|
+
MODULE_WORKING_DIR = '/tmp/'
|
|
19
|
+
|
|
20
|
+
def __init__(self, **kwargs):
|
|
21
|
+
|
|
22
|
+
self.shards = []
|
|
23
|
+
self.envIsUp = False
|
|
24
|
+
self.envIsHealthy = False
|
|
25
|
+
self.modulePath = kwargs.pop('modulePath')
|
|
26
|
+
self.moduleArgs = kwargs['moduleArgs']
|
|
27
|
+
self.shardsCount = kwargs.pop('shardsCount')
|
|
28
|
+
self.dmcBinaryPath = kwargs.pop('dmcBinaryPath')
|
|
29
|
+
useSlaves = kwargs.get('useSlaves', False)
|
|
30
|
+
|
|
31
|
+
self.preperModule()
|
|
32
|
+
startPort = 20000
|
|
33
|
+
totalRedises = self.shardsCount * (2 if useSlaves else 1)
|
|
34
|
+
for i in range(0, totalRedises, (2 if useSlaves else 1)):
|
|
35
|
+
shard = StandardEnv(port=startPort, serverId=(i + 1), password=SHARD_PASSWORD, modulePath=self.moduleSoFilePath, **kwargs)
|
|
36
|
+
self.shards.append(shard)
|
|
37
|
+
startPort += 2
|
|
38
|
+
|
|
39
|
+
self.ccs = CcsMock(redisBinaryPath=kwargs['redisBinaryPath'], directory=kwargs['dbDirPath'], useSlaves=kwargs['useSlaves'],
|
|
40
|
+
password=SHARD_PASSWORD, proxyPort=self.DMC_PORT, libPath=kwargs['libPath'])
|
|
41
|
+
self.dmc = Dmc(directory=kwargs['dbDirPath'], dmcBinaryPath=self.dmcBinaryPath, libPath=kwargs['libPath'])
|
|
42
|
+
self.envIsUp = False
|
|
43
|
+
|
|
44
|
+
def preperModule(self):
|
|
45
|
+
if self.modulePath is None:
|
|
46
|
+
self.moduleSoFilePath = None
|
|
47
|
+
self.moduleConfig = None
|
|
48
|
+
return
|
|
49
|
+
if not self.modulePath.endswith('zip'):
|
|
50
|
+
raise Exception('module on enterprise cluster must be a zip file')
|
|
51
|
+
with ZipFile(self.modulePath, 'r') as myzip:
|
|
52
|
+
moduleJson = [a.filename for a in myzip.infolist() if a.filename.endswith('.json')]
|
|
53
|
+
if len(moduleJson) != 1:
|
|
54
|
+
self.moduleSoFilePath = None
|
|
55
|
+
self.moduleConfig = None
|
|
56
|
+
return
|
|
57
|
+
moduleJson = moduleJson[0]
|
|
58
|
+
myzip.extractall(self.MODULE_WORKING_DIR)
|
|
59
|
+
with open(os.path.join(self.MODULE_WORKING_DIR, moduleJson), 'rt') as f:
|
|
60
|
+
self.moduleConfig = json.load(f)
|
|
61
|
+
self.moduleSoFilePath = os.path.join(self.MODULE_WORKING_DIR, self.moduleConfig['module_file'])
|
|
62
|
+
if self.moduleArgs is None:
|
|
63
|
+
self.moduleArgs = self.moduleConfig['command_line_args']
|
|
64
|
+
|
|
65
|
+
def printEnvData(self, prefix=''):
|
|
66
|
+
print(Colors.Yellow(prefix + 'bdb info:'))
|
|
67
|
+
print(Colors.Yellow(prefix + '\tlistening port:%d' % self.DMC_PORT))
|
|
68
|
+
print(Colors.Yellow(prefix + '\tshards count:%d' % len(self.shards)))
|
|
69
|
+
if self.modulePath:
|
|
70
|
+
print(Colors.Yellow(prefix + '\tzip module path:%s' % self.modulePath))
|
|
71
|
+
if self.moduleSoFilePath:
|
|
72
|
+
print(Colors.Yellow(prefix + '\tso module path:%s' % self.moduleSoFilePath))
|
|
73
|
+
if self.moduleArgs:
|
|
74
|
+
print(Colors.Yellow(prefix + '\tmodule args:%s' % self.moduleArgs))
|
|
75
|
+
for i, shard in enumerate(self.shards):
|
|
76
|
+
print(Colors.Yellow(prefix + 'shard: %d' % (i + 1)))
|
|
77
|
+
shard.printEnvData(prefix + '\t')
|
|
78
|
+
print(Colors.Yellow(prefix + 'ccs:'))
|
|
79
|
+
self.ccs.PrintEnvData(prefix + '\t')
|
|
80
|
+
print(Colors.Yellow(prefix + 'dmc:'))
|
|
81
|
+
self.dmc.PrintEnvData(prefix + '\t')
|
|
82
|
+
|
|
83
|
+
def startEnv(self, masters = True, slaves = True):
|
|
84
|
+
if self.envIsUp:
|
|
85
|
+
return # env is already up
|
|
86
|
+
for shard in self.shards:
|
|
87
|
+
shard.startEnv(masters, slaves)
|
|
88
|
+
|
|
89
|
+
ccs_bdb_config = {'shard_key_regex': '012.*\{(?<tag>.*)\}.*00a(?<tag>.*)',
|
|
90
|
+
'sharding': 'enabled' if self.shardsCount > 0 else 'disabled'}
|
|
91
|
+
|
|
92
|
+
extra_keys = {}
|
|
93
|
+
if self.moduleConfig:
|
|
94
|
+
ccs_bdb_config['module_list'] = self.moduleConfig['module_name']
|
|
95
|
+
extra_keys['module:%s' % self.moduleConfig['module_name']] = {'module_name': self.moduleConfig['module_name'],
|
|
96
|
+
'commands': ','.join([c['command_name'] for c in self.moduleConfig['commands']])}
|
|
97
|
+
for c in self.moduleConfig['commands']:
|
|
98
|
+
key_name = 'module_command:%s' % c['command_name']
|
|
99
|
+
extra_keys[key_name] = {}
|
|
100
|
+
for key, val in c.items():
|
|
101
|
+
extra_keys[key_name][key] = val
|
|
102
|
+
|
|
103
|
+
self.ccs.Start(self.shards, bdb_fields=ccs_bdb_config, legacy_hash_slots=False, extra_keys=extra_keys)
|
|
104
|
+
self.dmc.Start()
|
|
105
|
+
con = self.getConnection()
|
|
106
|
+
wait_for_conn(con, command='sping', shouldBe=['SPONG 0' for i in self.shards])
|
|
107
|
+
self.envIsUp = True
|
|
108
|
+
self.envIsHealthy = True
|
|
109
|
+
|
|
110
|
+
def stopEnv(self, masters = True, slaves = True):
|
|
111
|
+
for shard in self.shards:
|
|
112
|
+
shard.stopEnv(masters, slaves)
|
|
113
|
+
self.envIsUp = self.envIsUp or shard.envIsUp
|
|
114
|
+
self.envIsHealthy = self.envIsHealthy and shard.envIsUp
|
|
115
|
+
self.ccs.Stop()
|
|
116
|
+
self.dmc.Stop()
|
|
117
|
+
|
|
118
|
+
def getConnection(self, shardId=1):
|
|
119
|
+
return redis.Redis('localhost', self.DMC_PORT)
|
|
120
|
+
|
|
121
|
+
def getSlaveConnection(self):
|
|
122
|
+
raise Exception('unsupported')
|
|
123
|
+
|
|
124
|
+
def flush(self):
|
|
125
|
+
self.getConnection().flushall()
|
|
126
|
+
|
|
127
|
+
def dumpAndReload(self, restart=False, shardId=None, timeout_sec=40):
|
|
128
|
+
if shardId is None:
|
|
129
|
+
for shard in self.shards:
|
|
130
|
+
shard.dumpAndReload(restart=restart)
|
|
131
|
+
self.dmc.Stop()
|
|
132
|
+
self.dmc.Start()
|
|
133
|
+
con = self.getConnection()
|
|
134
|
+
wait_for_conn(con, command='sping', shouldBe=['SPONG 0' for i in self.shards])
|
|
135
|
+
else:
|
|
136
|
+
self.shards[shardId - 1].dumpAndReload(restart=restart, shardId=None)
|
|
137
|
+
|
|
138
|
+
def broadcast(self, *cmd):
|
|
139
|
+
for shard in self.shards:
|
|
140
|
+
shard.broadcast(*cmd)
|
|
141
|
+
|
|
142
|
+
def checkExitCode(self):
|
|
143
|
+
for shard in self.shards:
|
|
144
|
+
if not shard.checkExitCode():
|
|
145
|
+
return False
|
|
146
|
+
return True
|
|
147
|
+
|
|
148
|
+
def exists(self, val):
|
|
149
|
+
return self.getConnection().exists(val)
|
|
150
|
+
|
|
151
|
+
def hmset(self, *args):
|
|
152
|
+
return self.getConnection().hmset(*args)
|
|
153
|
+
|
|
154
|
+
def keys(self, reg):
|
|
155
|
+
return self.getConnection().keys(reg)
|
|
156
|
+
|
|
157
|
+
def isUp(self):
|
|
158
|
+
raise Exception('unsupported operation')
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
import os.path
|
|
3
|
+
import shutil
|
|
4
|
+
import distro
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from RLTest.utils import Colors
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
OS_NAME = distro.linux_distribution()[2]
|
|
12
|
+
REPO_ROOT = os.path.expanduser('~/.RLTest')
|
|
13
|
+
ENTERPRISE_VERSION = '5.2.0'
|
|
14
|
+
ENTERPRISE_SUB_VERSION = '14'
|
|
15
|
+
ENTERPRISE_TAR_FILE_NAME = 'redislabs-%s-%s-%s-amd64.tar' % (
|
|
16
|
+
ENTERPRISE_VERSION, ENTERPRISE_SUB_VERSION, OS_NAME)
|
|
17
|
+
ENTERPRISE_URL = 'https://s3.amazonaws.com/rlec-downloads/%s/%s' % (
|
|
18
|
+
ENTERPRISE_VERSION, ENTERPRISE_TAR_FILE_NAME)
|
|
19
|
+
DEBIAN_PKG_NAME = 'redislabs_%s-%s~%s_amd64.deb' % (
|
|
20
|
+
ENTERPRISE_VERSION, ENTERPRISE_SUB_VERSION, OS_NAME)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BinaryRepository(object):
|
|
24
|
+
"""
|
|
25
|
+
Installation manager for Redis Enterprise.
|
|
26
|
+
The long-term idea behind this is to allow for managing different versions, etc.
|
|
27
|
+
but for now it's just here to cut some code out of the main executable
|
|
28
|
+
"""
|
|
29
|
+
def __init__(self, root=REPO_ROOT, url=ENTERPRISE_URL, debname=DEBIAN_PKG_NAME):
|
|
30
|
+
self.root = root
|
|
31
|
+
self.url = url
|
|
32
|
+
self.debname = debname
|
|
33
|
+
|
|
34
|
+
def download_binaries(self, binariesName='binaries.tar'):
|
|
35
|
+
print(Colors.Yellow('installing enterprise binaries'))
|
|
36
|
+
print(Colors.Yellow('creating RLTest working dir: %s' % self.root))
|
|
37
|
+
try:
|
|
38
|
+
shutil.rmtree(self.root)
|
|
39
|
+
os.makedirs(self.root)
|
|
40
|
+
except Exception:
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
print(Colors.Yellow('download binaries'))
|
|
44
|
+
args = ['wget', self.url, '-O', os.path.join(self.root, binariesName)]
|
|
45
|
+
process = subprocess.Popen(args=args, stdout=sys.stdout,
|
|
46
|
+
stderr=sys.stdout)
|
|
47
|
+
process.wait()
|
|
48
|
+
if process.poll() != 0:
|
|
49
|
+
raise Exception('failed to download enterprise binaries from s3')
|
|
50
|
+
|
|
51
|
+
print(Colors.Yellow('extracting binaries'))
|
|
52
|
+
|
|
53
|
+
args = ['tar', '-xvf', os.path.join(self.root, binariesName),
|
|
54
|
+
'--directory', self.root, self.debname]
|
|
55
|
+
process = subprocess.Popen(args=args, stdout=sys.stdout, stderr=sys.stdout)
|
|
56
|
+
process.wait()
|
|
57
|
+
if process.poll() != 0:
|
|
58
|
+
raise Exception(
|
|
59
|
+
'failed to extract binaries to %s' % self.self.root)
|
|
60
|
+
|
|
61
|
+
# TODO: Support centos that does not have dpkg command
|
|
62
|
+
args = ['dpkg', '-x', os.path.join(self.root, self.debname),
|
|
63
|
+
self.root]
|
|
64
|
+
process = subprocess.Popen(args=args, stdout=sys.stdout,
|
|
65
|
+
stderr=sys.stdout)
|
|
66
|
+
process.wait()
|
|
67
|
+
if process.poll() != 0:
|
|
68
|
+
raise Exception(
|
|
69
|
+
'failed to extract binaries to %s' % self.self.root)
|
|
70
|
+
|
|
71
|
+
print(Colors.Yellow('finished installing enterprise binaries'))
|