]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/ragweed.py
2 Run a set of s3 tests on rgw.
4 from cStringIO
import StringIO
5 from configobj
import ConfigObj
13 import util
.rgw
as rgw_utils
15 from teuthology
import misc
as teuthology
16 from teuthology
import contextutil
17 from teuthology
.config
import config
as teuth_config
18 from teuthology
.orchestra
import run
19 from teuthology
.orchestra
.connection
import split_user
21 log
= logging
.getLogger(__name__
)
23 @contextlib.contextmanager
24 def download(ctx
, config
):
26 Download the s3 tests from the git builder.
27 Remove downloaded s3 file upon exit.
29 The context passed in should be identical to the context
30 passed in to the main task.
32 assert isinstance(config
, dict)
33 log
.info('Downloading ragweed...')
34 testdir
= teuthology
.get_testdir(ctx
)
35 s3_branches
= [ 'master', 'nautilus', 'mimic', 'luminous', 'kraken', 'jewel' ]
36 for (client
, cconf
) in config
.items():
38 branch
= cconf
.get('force-branch', None)
40 default_branch
= cconf
.get('default-branch', None)
41 ceph_branch
= ctx
.config
.get('branch')
42 suite_branch
= ctx
.config
.get('suite_branch', ceph_branch
)
43 ragweed_repo
= ctx
.config
.get('ragweed_repo', teuth_config
.ceph_git_base_url
+ 'ragweed.git')
44 if suite_branch
in s3_branches
:
45 branch
= cconf
.get('branch', 'ceph-' + suite_branch
)
47 branch
= cconf
.get('branch', suite_branch
)
50 "Could not determine what branch to use for ragweed!")
52 log
.info("Using branch '%s' for ragweed", branch
)
53 sha1
= cconf
.get('sha1')
55 ctx
.cluster
.only(client
).run(
60 '{tdir}/ragweed'.format(tdir
=testdir
),
63 except Exception as e
:
64 if not default_branch
:
66 ctx
.cluster
.only(client
).run(
71 '{tdir}/ragweed'.format(tdir
=testdir
),
76 ctx
.cluster
.only(client
).run(
78 'cd', '{tdir}/ragweed'.format(tdir
=testdir
),
80 'git', 'reset', '--hard', sha1
,
86 log
.info('Removing ragweed...')
87 testdir
= teuthology
.get_testdir(ctx
)
89 ctx
.cluster
.only(client
).run(
93 '{tdir}/ragweed'.format(tdir
=testdir
),
98 def _config_user(ragweed_conf
, section
, user
):
100 Configure users for this section by stashing away keys, ids, and
103 ragweed_conf
[section
].setdefault('user_id', user
)
104 ragweed_conf
[section
].setdefault('email', '{user}+test@test.test'.format(user
=user
))
105 ragweed_conf
[section
].setdefault('display_name', 'Mr. {user}'.format(user
=user
))
106 ragweed_conf
[section
].setdefault('access_key', ''.join(random
.choice(string
.uppercase
) for i
in xrange(20)))
107 ragweed_conf
[section
].setdefault('secret_key', base64
.b64encode(os
.urandom(40)))
110 @contextlib.contextmanager
111 def create_users(ctx
, config
, run_stages
):
113 Create a main and an alternate s3 user.
115 assert isinstance(config
, dict)
117 for client
, properties
in config
['config'].iteritems():
118 run_stages
[client
] = string
.split(properties
.get('stages', 'prepare,check'), ',')
120 log
.info('Creating rgw users...')
121 testdir
= teuthology
.get_testdir(ctx
)
122 users
= {'user regular': 'ragweed', 'user system': 'sysuser'}
123 for client
in config
['clients']:
124 if not 'prepare' in run_stages
[client
]:
125 # should have been prepared in a previous run
128 ragweed_conf
= config
['ragweed_conf'][client
]
129 ragweed_conf
.setdefault('fixtures', {})
130 ragweed_conf
['rgw'].setdefault('bucket_prefix', 'test-' + client
)
131 for section
, user
in users
.iteritems():
132 _config_user(ragweed_conf
, section
, '{user}.{client}'.format(user
=user
, client
=client
))
133 log
.debug('Creating user {user} on {host}'.format(user
=ragweed_conf
[section
]['user_id'], host
=client
))
134 if user
== 'sysuser':
138 ctx
.cluster
.only(client
).run(
142 '{tdir}/archive/coverage'.format(tdir
=testdir
),
146 '--uid', ragweed_conf
[section
]['user_id'],
147 '--display-name', ragweed_conf
[section
]['display_name'],
148 '--access-key', ragweed_conf
[section
]['access_key'],
149 '--secret', ragweed_conf
[section
]['secret_key'],
150 '--email', ragweed_conf
[section
]['email'],
157 for client
in config
['clients']:
158 if not 'check' in run_stages
[client
]:
159 # only remove user if went through the check stage
161 for user
in users
.itervalues():
162 uid
= '{user}.{client}'.format(user
=user
, client
=client
)
163 ctx
.cluster
.only(client
).run(
167 '{tdir}/archive/coverage'.format(tdir
=testdir
),
177 @contextlib.contextmanager
178 def configure(ctx
, config
, run_stages
):
180 Configure the ragweed. This includes the running of the
181 bootstrap code and the updating of local conf files.
183 assert isinstance(config
, dict)
184 log
.info('Configuring ragweed...')
185 testdir
= teuthology
.get_testdir(ctx
)
186 for client
, properties
in config
['clients'].iteritems():
187 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
191 '{tdir}/ragweed'.format(tdir
=testdir
),
197 preparing
= 'prepare' in run_stages
[client
]
199 # should have been prepared in a previous run
202 ragweed_conf
= config
['ragweed_conf'][client
]
203 if properties
is not None and 'rgw_server' in properties
:
205 for target
, roles
in zip(ctx
.config
['targets'].iterkeys(), ctx
.config
['roles']):
206 log
.info('roles: ' + str(roles
))
207 log
.info('target: ' + str(target
))
208 if properties
['rgw_server'] in roles
:
209 _
, host
= split_user(target
)
210 assert host
is not None, "Invalid client specified as the rgw_server"
211 ragweed_conf
['rgw']['host'] = host
213 ragweed_conf
['rgw']['host'] = 'localhost'
215 if properties
is not None and 'slow_backend' in properties
:
216 ragweed_conf
['fixtures']['slow backend'] = properties
['slow_backend']
219 ragweed_conf
.write(conf_fp
)
220 teuthology
.write_file(
222 path
='{tdir}/archive/ragweed.{client}.conf'.format(tdir
=testdir
, client
=client
),
223 data
=conf_fp
.getvalue(),
226 log
.info('Configuring boto...')
227 boto_src
= os
.path
.join(os
.path
.dirname(__file__
), 'boto.cfg.template')
228 for client
, properties
in config
['clients'].iteritems():
229 with
file(boto_src
, 'rb') as f
:
230 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
231 conf
= f
.read().format(
232 idle_timeout
=config
.get('idle_timeout', 30)
234 teuthology
.write_file(
236 path
='{tdir}/boto.cfg'.format(tdir
=testdir
),
244 log
.info('Cleaning up boto...')
245 for client
, properties
in config
['clients'].iteritems():
246 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
250 '{tdir}/boto.cfg'.format(tdir
=testdir
),
254 @contextlib.contextmanager
255 def run_tests(ctx
, config
, run_stages
):
257 Run the ragweed after everything is set up.
259 :param ctx: Context passed to task
260 :param config: specific configuration information
262 assert isinstance(config
, dict)
263 testdir
= teuthology
.get_testdir(ctx
)
264 attrs
= ["!fails_on_rgw"]
265 for client
, client_config
in config
.iteritems():
266 stages
= string
.join(run_stages
[client
], ',')
268 'RAGWEED_CONF={tdir}/archive/ragweed.{client}.conf'.format(tdir
=testdir
, client
=client
),
269 'RAGWEED_STAGES={stages}'.format(stages
=stages
),
270 'BOTO_CONFIG={tdir}/boto.cfg'.format(tdir
=testdir
),
271 '{tdir}/ragweed/virtualenv/bin/nosetests'.format(tdir
=testdir
),
273 '{tdir}/ragweed'.format(tdir
=testdir
),
275 '-a', ','.join(attrs
),
277 if client_config
is not None and 'extra_args' in client_config
:
278 args
.extend(client_config
['extra_args'])
280 ctx
.cluster
.only(client
).run(
282 label
="ragweed tests against rgw"
286 @contextlib.contextmanager
287 def task(ctx
, config
):
289 Run the ragweed suite against rgw.
291 To run all tests on all clients::
298 To restrict testing to particular clients::
303 - ragweed: [client.0]
305 To run against a server on client.1 and increase the boto timeout to 10m::
314 stages: prepare,check
316 To pass extra arguments to nose (e.g. to run a certain test)::
323 extra_args: ['test_s3:test_object_acl_grand_public_read']
325 extra_args: ['--exclude', 'test_100_continue']
327 assert hasattr(ctx
, 'rgw'), 'ragweed must run after the rgw task'
328 assert config
is None or isinstance(config
, list) \
329 or isinstance(config
, dict), \
330 "task ragweed only supports a list or dictionary for configuration"
331 all_clients
= ['client.{id}'.format(id=id_
)
332 for id_
in teuthology
.all_roles_of_type(ctx
.cluster
, 'client')]
335 if isinstance(config
, list):
336 config
= dict.fromkeys(config
)
337 clients
= config
.keys()
339 overrides
= ctx
.config
.get('overrides', {})
340 # merge each client section, not the top level.
341 for client
in config
.iterkeys():
342 if not config
[client
]:
344 teuthology
.deep_merge(config
[client
], overrides
.get('ragweed', {}))
346 log
.debug('ragweed config is %s', config
)
349 for client
in clients
:
350 endpoint
= ctx
.rgw
.role_endpoints
.get(client
)
351 assert endpoint
, 'ragweed: no rgw endpoint for {}'.format(client
)
353 ragweed_conf
[client
] = ConfigObj(
358 'port' : endpoint
.port
,
359 'is_secure' : endpoint
.cert
is not None,
366 'ceph_conf' : '/etc/ceph/ceph.conf',
373 with contextutil
.nested(
374 lambda: download(ctx
=ctx
, config
=config
),
375 lambda: create_users(ctx
=ctx
, config
=dict(
377 ragweed_conf
=ragweed_conf
,
380 run_stages
=run_stages
),
381 lambda: configure(ctx
=ctx
, config
=dict(
383 ragweed_conf
=ragweed_conf
,
385 run_stages
=run_stages
),
386 lambda: run_tests(ctx
=ctx
, config
=config
, run_stages
=run_stages
),