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