]> git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/s3readwrite.py
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / qa / tasks / s3readwrite.py
1 """
2 Run rgw s3 readwite tests
3 """
4 from cStringIO import StringIO
5 import base64
6 import contextlib
7 import logging
8 import os
9 import random
10 import string
11 import yaml
12
13 from teuthology import misc as teuthology
14 from teuthology import contextutil
15 from teuthology.config import config as teuth_config
16 from teuthology.orchestra import run
17 from teuthology.orchestra.connection import split_user
18
19 log = logging.getLogger(__name__)
20
21
22 @contextlib.contextmanager
23 def download(ctx, config):
24 """
25 Download the s3 tests from the git builder.
26 Remove downloaded s3 file upon exit.
27
28 The context passed in should be identical to the context
29 passed in to the main task.
30 """
31 assert isinstance(config, dict)
32 log.info('Downloading s3-tests...')
33 testdir = teuthology.get_testdir(ctx)
34 for (client, cconf) in config.items():
35 branch = cconf.get('force-branch', None)
36 if not branch:
37 branch = cconf.get('branch', 'master')
38 sha1 = cconf.get('sha1')
39 ctx.cluster.only(client).run(
40 args=[
41 'git', 'clone',
42 '-b', branch,
43 teuth_config.ceph_git_base_url + 's3-tests.git',
44 '{tdir}/s3-tests'.format(tdir=testdir),
45 ],
46 )
47 if sha1 is not None:
48 ctx.cluster.only(client).run(
49 args=[
50 'cd', '{tdir}/s3-tests'.format(tdir=testdir),
51 run.Raw('&&'),
52 'git', 'reset', '--hard', sha1,
53 ],
54 )
55 try:
56 yield
57 finally:
58 log.info('Removing s3-tests...')
59 testdir = teuthology.get_testdir(ctx)
60 for client in config:
61 ctx.cluster.only(client).run(
62 args=[
63 'rm',
64 '-rf',
65 '{tdir}/s3-tests'.format(tdir=testdir),
66 ],
67 )
68
69
70 def _config_user(s3tests_conf, section, user):
71 """
72 Configure users for this section by stashing away keys, ids, and
73 email addresses.
74 """
75 s3tests_conf[section].setdefault('user_id', user)
76 s3tests_conf[section].setdefault('email', '{user}+test@test.test'.format(user=user))
77 s3tests_conf[section].setdefault('display_name', 'Mr. {user}'.format(user=user))
78 s3tests_conf[section].setdefault('access_key', ''.join(random.choice(string.uppercase) for i in xrange(20)))
79 s3tests_conf[section].setdefault('secret_key', base64.b64encode(os.urandom(40)))
80
81 @contextlib.contextmanager
82 def create_users(ctx, config):
83 """
84 Create a default s3 user.
85 """
86 assert isinstance(config, dict)
87 log.info('Creating rgw users...')
88 testdir = teuthology.get_testdir(ctx)
89 users = {'s3': 'foo'}
90 cached_client_user_names = dict()
91 for client in config['clients']:
92 cached_client_user_names[client] = dict()
93 s3tests_conf = config['s3tests_conf'][client]
94 s3tests_conf.setdefault('readwrite', {})
95 s3tests_conf['readwrite'].setdefault('bucket', 'rwtest-' + client + '-{random}-')
96 s3tests_conf['readwrite'].setdefault('readers', 10)
97 s3tests_conf['readwrite'].setdefault('writers', 3)
98 s3tests_conf['readwrite'].setdefault('duration', 300)
99 s3tests_conf['readwrite'].setdefault('files', {})
100 rwconf = s3tests_conf['readwrite']
101 rwconf['files'].setdefault('num', 10)
102 rwconf['files'].setdefault('size', 2000)
103 rwconf['files'].setdefault('stddev', 500)
104 for section, user in users.iteritems():
105 _config_user(s3tests_conf, section, '{user}.{client}'.format(user=user, client=client))
106 log.debug('creating user {user} on {client}'.format(user=s3tests_conf[section]['user_id'],
107 client=client))
108
109 # stash the 'delete_user' flag along with user name for easier cleanup
110 delete_this_user = True
111 if 'delete_user' in s3tests_conf['s3']:
112 delete_this_user = s3tests_conf['s3']['delete_user']
113 log.debug('delete_user set to {flag} for {client}'.format(flag=delete_this_user, client=client))
114 cached_client_user_names[client][section+user] = (s3tests_conf[section]['user_id'], delete_this_user)
115
116 # skip actual user creation if the create_user flag is set to false for this client
117 if 'create_user' in s3tests_conf['s3'] and s3tests_conf['s3']['create_user'] == False:
118 log.debug('create_user set to False, skipping user creation for {client}'.format(client=client))
119 continue
120 else:
121 ctx.cluster.only(client).run(
122 args=[
123 'adjust-ulimits',
124 'ceph-coverage',
125 '{tdir}/archive/coverage'.format(tdir=testdir),
126 'radosgw-admin',
127 '-n', client,
128 'user', 'create',
129 '--uid', s3tests_conf[section]['user_id'],
130 '--display-name', s3tests_conf[section]['display_name'],
131 '--access-key', s3tests_conf[section]['access_key'],
132 '--secret', s3tests_conf[section]['secret_key'],
133 '--email', s3tests_conf[section]['email'],
134 ],
135 )
136 try:
137 yield
138 finally:
139 for client in config['clients']:
140 for section, user in users.iteritems():
141 #uid = '{user}.{client}'.format(user=user, client=client)
142 real_uid, delete_this_user = cached_client_user_names[client][section+user]
143 if delete_this_user:
144 ctx.cluster.only(client).run(
145 args=[
146 'adjust-ulimits',
147 'ceph-coverage',
148 '{tdir}/archive/coverage'.format(tdir=testdir),
149 'radosgw-admin',
150 '-n', client,
151 'user', 'rm',
152 '--uid', real_uid,
153 '--purge-data',
154 ],
155 )
156 else:
157 log.debug('skipping delete for user {uid} on {client}'.format(uid=real_uid, client=client))
158
159 @contextlib.contextmanager
160 def configure(ctx, config):
161 """
162 Configure the s3-tests. This includes the running of the
163 bootstrap code and the updating of local conf files.
164 """
165 assert isinstance(config, dict)
166 log.info('Configuring s3-readwrite-tests...')
167 for client, properties in config['clients'].iteritems():
168 s3tests_conf = config['s3tests_conf'][client]
169 if properties is not None and 'rgw_server' in properties:
170 host = None
171 for target, roles in zip(ctx.config['targets'].iterkeys(), ctx.config['roles']):
172 log.info('roles: ' + str(roles))
173 log.info('target: ' + str(target))
174 if properties['rgw_server'] in roles:
175 _, host = split_user(target)
176 assert host is not None, "Invalid client specified as the rgw_server"
177 s3tests_conf['s3']['host'] = host
178 else:
179 s3tests_conf['s3']['host'] = 'localhost'
180
181 def_conf = s3tests_conf['DEFAULT']
182 s3tests_conf['s3'].setdefault('port', def_conf['port'])
183 s3tests_conf['s3'].setdefault('is_secure', def_conf['is_secure'])
184
185 (remote,) = ctx.cluster.only(client).remotes.keys()
186 remote.run(
187 args=[
188 'cd',
189 '{tdir}/s3-tests'.format(tdir=teuthology.get_testdir(ctx)),
190 run.Raw('&&'),
191 './bootstrap',
192 ],
193 )
194 conf_fp = StringIO()
195 conf = dict(
196 s3=s3tests_conf['s3'],
197 readwrite=s3tests_conf['readwrite'],
198 )
199 yaml.safe_dump(conf, conf_fp, default_flow_style=False)
200 teuthology.write_file(
201 remote=remote,
202 path='{tdir}/archive/s3readwrite.{client}.config.yaml'.format(tdir=teuthology.get_testdir(ctx), client=client),
203 data=conf_fp.getvalue(),
204 )
205 yield
206
207
208 @contextlib.contextmanager
209 def run_tests(ctx, config):
210 """
211 Run the s3readwrite tests after everything is set up.
212
213 :param ctx: Context passed to task
214 :param config: specific configuration information
215 """
216 assert isinstance(config, dict)
217 testdir = teuthology.get_testdir(ctx)
218 for client, client_config in config.iteritems():
219 (remote,) = ctx.cluster.only(client).remotes.keys()
220 conf = teuthology.get_file(remote, '{tdir}/archive/s3readwrite.{client}.config.yaml'.format(tdir=testdir, client=client))
221 args = [
222 '{tdir}/s3-tests/virtualenv/bin/s3tests-test-readwrite'.format(tdir=testdir),
223 ]
224 if client_config is not None and 'extra_args' in client_config:
225 args.extend(client_config['extra_args'])
226
227 ctx.cluster.only(client).run(
228 args=args,
229 stdin=conf,
230 )
231 yield
232
233
234 @contextlib.contextmanager
235 def task(ctx, config):
236 """
237 Run the s3tests-test-readwrite suite against rgw.
238
239 To run all tests on all clients::
240
241 tasks:
242 - ceph:
243 - rgw:
244 - s3readwrite:
245
246 To restrict testing to particular clients::
247
248 tasks:
249 - ceph:
250 - rgw: [client.0]
251 - s3readwrite: [client.0]
252
253 To run against a server on client.1::
254
255 tasks:
256 - ceph:
257 - rgw: [client.1]
258 - s3readwrite:
259 client.0:
260 rgw_server: client.1
261
262 To pass extra test arguments
263
264 tasks:
265 - ceph:
266 - rgw: [client.0]
267 - s3readwrite:
268 client.0:
269 readwrite:
270 bucket: mybucket
271 readers: 10
272 writers: 3
273 duration: 600
274 files:
275 num: 10
276 size: 2000
277 stddev: 500
278 client.1:
279 ...
280
281 To override s3 configuration
282
283 tasks:
284 - ceph:
285 - rgw: [client.0]
286 - s3readwrite:
287 client.0:
288 s3:
289 user_id: myuserid
290 display_name: myname
291 email: my@email
292 access_key: myaccesskey
293 secret_key: mysecretkey
294
295 """
296 assert config is None or isinstance(config, list) \
297 or isinstance(config, dict), \
298 "task s3tests only supports a list or dictionary for configuration"
299 all_clients = ['client.{id}'.format(id=id_)
300 for id_ in teuthology.all_roles_of_type(ctx.cluster, 'client')]
301 if config is None:
302 config = all_clients
303 if isinstance(config, list):
304 config = dict.fromkeys(config)
305 clients = config.keys()
306
307 overrides = ctx.config.get('overrides', {})
308 # merge each client section, not the top level.
309 for client in config.iterkeys():
310 if not config[client]:
311 config[client] = {}
312 teuthology.deep_merge(config[client], overrides.get('s3readwrite', {}))
313
314 log.debug('in s3readwrite, config is %s', config)
315
316 s3tests_conf = {}
317 for client in clients:
318 if config[client] is None:
319 config[client] = {}
320 config[client].setdefault('s3', {})
321 config[client].setdefault('readwrite', {})
322
323 s3tests_conf[client] = ({
324 'DEFAULT':
325 {
326 'port' : 7280,
327 'is_secure' : False,
328 },
329 'readwrite' : config[client]['readwrite'],
330 's3' : config[client]['s3'],
331 })
332
333 with contextutil.nested(
334 lambda: download(ctx=ctx, config=config),
335 lambda: create_users(ctx=ctx, config=dict(
336 clients=clients,
337 s3tests_conf=s3tests_conf,
338 )),
339 lambda: configure(ctx=ctx, config=dict(
340 clients=config,
341 s3tests_conf=s3tests_conf,
342 )),
343 lambda: run_tests(ctx=ctx, config=config),
344 ):
345 pass
346 yield