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