]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/ragweed.py
2 Run a set of s3 tests on rgw.
5 from configobj
import ConfigObj
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
18 log
= logging
.getLogger(__name__
)
21 def get_ragweed_branches(config
, client_conf
):
23 figure out the ragweed branch according to the per-client settings
25 use force-branch is specified, and fall back to the ones deduced using ceph
28 force_branch
= client_conf
.get('force-branch', None)
32 S3_BRANCHES
= ['master', 'nautilus', 'mimic',
33 'luminous', 'kraken', 'jewel']
34 ceph_branch
= config
.get('branch')
35 suite_branch
= config
.get('suite_branch', ceph_branch
)
36 if suite_branch
in S3_BRANCHES
:
37 branch
= client_conf
.get('branch', 'ceph-' + suite_branch
)
39 branch
= client_conf
.get('branch', suite_branch
)
40 default_branch
= client_conf
.get('default-branch', None)
42 return [branch
, default_branch
]
47 @contextlib.contextmanager
48 def download(ctx
, config
):
50 Download the s3 tests from the git builder.
51 Remove downloaded s3 file upon exit.
53 The context passed in should be identical to the context
54 passed in to the main task.
56 assert isinstance(config
, dict)
57 log
.info('Downloading ragweed...')
58 testdir
= teuthology
.get_testdir(ctx
)
59 for (client
, cconf
) in config
.items():
60 ragweed_repo
= ctx
.config
.get('ragweed_repo',
61 teuth_config
.ceph_git_base_url
+ 'ragweed.git')
62 for branch
in get_ragweed_branches(ctx
.config
, cconf
):
63 log
.info("Using branch '%s' for ragweed", branch
)
65 ctx
.cluster
.only(client
).sh(
66 script
=f
'git clone -b {branch} {ragweed_repo} {testdir}/ragweed')
68 except Exception as e
:
73 sha1
= cconf
.get('sha1')
75 ctx
.cluster
.only(client
).run(
77 'cd', '{tdir}/ragweed'.format(tdir
=testdir
),
79 'git', 'reset', '--hard', sha1
,
85 log
.info('Removing ragweed...')
86 testdir
= teuthology
.get_testdir(ctx
)
88 ctx
.cluster
.only(client
).run(
92 '{tdir}/ragweed'.format(tdir
=testdir
),
97 def _config_user(ragweed_conf
, section
, user
):
99 Configure users for this section by stashing away keys, ids, and
102 ragweed_conf
[section
].setdefault('user_id', user
)
103 ragweed_conf
[section
].setdefault('email', '{user}+test@test.test'.format(user
=user
))
104 ragweed_conf
[section
].setdefault('display_name', 'Mr. {user}'.format(user
=user
))
105 ragweed_conf
[section
].setdefault('access_key', ''.join(random
.choice(string
.ascii_uppercase
) for i
in range(20)))
106 ragweed_conf
[section
].setdefault('secret_key', base64
.b64encode(os
.urandom(40)).decode('ascii'))
109 @contextlib.contextmanager
110 def create_users(ctx
, config
, run_stages
):
112 Create a main and an alternate s3 user.
114 assert isinstance(config
, dict)
116 for client
, properties
in config
['config'].items():
117 run_stages
[client
] = properties
.get('stages', 'prepare,check').split(',')
119 log
.info('Creating rgw users...')
120 testdir
= teuthology
.get_testdir(ctx
)
121 users
= {'user regular': 'ragweed', 'user system': 'sysuser'}
122 for client
in config
['clients']:
123 if not 'prepare' in run_stages
[client
]:
124 # should have been prepared in a previous run
127 ragweed_conf
= config
['ragweed_conf'][client
]
128 ragweed_conf
.setdefault('fixtures', {})
129 ragweed_conf
['rgw'].setdefault('bucket_prefix', 'test-' + client
)
130 for section
, user
in users
.items():
131 _config_user(ragweed_conf
, section
, '{user}.{client}'.format(user
=user
, client
=client
))
132 log
.debug('Creating user {user} on {host}'.format(user
=ragweed_conf
[section
]['user_id'], host
=client
))
133 if user
== 'sysuser':
137 ctx
.cluster
.only(client
).run(
141 '{tdir}/archive/coverage'.format(tdir
=testdir
),
145 '--uid', ragweed_conf
[section
]['user_id'],
146 '--display-name', ragweed_conf
[section
]['display_name'],
147 '--access-key', ragweed_conf
[section
]['access_key'],
148 '--secret', ragweed_conf
[section
]['secret_key'],
149 '--email', ragweed_conf
[section
]['email'],
156 for client
in config
['clients']:
157 if not 'check' in run_stages
[client
]:
158 # only remove user if went through the check stage
160 for user
in users
.values():
161 uid
= '{user}.{client}'.format(user
=user
, client
=client
)
162 ctx
.cluster
.only(client
).run(
166 '{tdir}/archive/coverage'.format(tdir
=testdir
),
176 @contextlib.contextmanager
177 def configure(ctx
, config
, run_stages
):
179 Configure the ragweed. This includes the running of the
180 bootstrap code and the updating of local conf files.
182 assert isinstance(config
, dict)
183 log
.info('Configuring ragweed...')
184 testdir
= teuthology
.get_testdir(ctx
)
185 for client
, properties
in config
['clients'].items():
186 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
190 '{tdir}/ragweed'.format(tdir
=testdir
),
196 preparing
= 'prepare' in run_stages
[client
]
198 # should have been prepared in a previous run
201 ragweed_conf
= config
['ragweed_conf'][client
]
202 if properties
is not None and 'slow_backend' in properties
:
203 ragweed_conf
['fixtures']['slow backend'] = properties
['slow_backend']
206 ragweed_conf
.write(conf_fp
)
208 path
='{tdir}/archive/ragweed.{client}.conf'.format(tdir
=testdir
, client
=client
),
209 data
=conf_fp
.getvalue(),
212 log
.info('Configuring boto...')
213 boto_src
= os
.path
.join(os
.path
.dirname(__file__
), 'boto.cfg.template')
214 for client
, properties
in config
['clients'].items():
215 with
open(boto_src
, 'r') as f
:
216 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
217 conf
= f
.read().format(
218 idle_timeout
=config
.get('idle_timeout', 30)
220 remote
.write_file('{tdir}/boto.cfg'.format(tdir
=testdir
), conf
)
226 log
.info('Cleaning up boto...')
227 for client
, properties
in config
['clients'].items():
228 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
232 '{tdir}/boto.cfg'.format(tdir
=testdir
),
236 @contextlib.contextmanager
237 def run_tests(ctx
, config
, run_stages
):
239 Run the ragweed after everything is set up.
241 :param ctx: Context passed to task
242 :param config: specific configuration information
244 assert isinstance(config
, dict)
245 testdir
= teuthology
.get_testdir(ctx
)
246 attrs
= ["!fails_on_rgw"]
247 for client
, client_config
in config
.items():
248 stages
= ','.join(run_stages
[client
])
250 'RAGWEED_CONF={tdir}/archive/ragweed.{client}.conf'.format(tdir
=testdir
, client
=client
),
251 'RAGWEED_STAGES={stages}'.format(stages
=stages
),
252 'BOTO_CONFIG={tdir}/boto.cfg'.format(tdir
=testdir
),
253 '{tdir}/ragweed/virtualenv/bin/python'.format(tdir
=testdir
),
256 '{tdir}/ragweed'.format(tdir
=testdir
),
258 '-a', ','.join(attrs
),
260 if client_config
is not None and 'extra_args' in client_config
:
261 args
.extend(client_config
['extra_args'])
263 ctx
.cluster
.only(client
).run(
265 label
="ragweed tests against rgw"
269 @contextlib.contextmanager
270 def task(ctx
, config
):
272 Run the ragweed suite against rgw.
274 To run all tests on all clients::
281 To restrict testing to particular clients::
286 - ragweed: [client.0]
288 To run against a server on client.1 and increase the boto timeout to 10m::
297 stages: prepare,check
299 To pass extra arguments to nose (e.g. to run a certain test)::
306 extra_args: ['test_s3:test_object_acl_grand_public_read']
308 extra_args: ['--exclude', 'test_100_continue']
310 assert hasattr(ctx
, 'rgw'), 'ragweed must run after the rgw task'
311 assert config
is None or isinstance(config
, list) \
312 or isinstance(config
, dict), \
313 "task ragweed only supports a list or dictionary for configuration"
314 all_clients
= ['client.{id}'.format(id=id_
)
315 for id_
in teuthology
.all_roles_of_type(ctx
.cluster
, 'client')]
318 if isinstance(config
, list):
319 config
= dict.fromkeys(config
)
320 clients
= config
.keys()
322 overrides
= ctx
.config
.get('overrides', {})
323 # merge each client section, not the top level.
324 for client
in config
.keys():
325 if not config
[client
]:
327 teuthology
.deep_merge(config
[client
], overrides
.get('ragweed', {}))
329 log
.debug('ragweed config is %s', config
)
332 for client
in clients
:
333 # use rgw_server endpoint if given, or default to same client
334 target
= config
[client
].get('rgw_server', client
)
336 endpoint
= ctx
.rgw
.role_endpoints
.get(target
)
337 assert endpoint
, 'ragweed: no rgw endpoint for {}'.format(target
)
339 ragweed_conf
[client
] = ConfigObj(
344 'host' : endpoint
.dns_name
,
345 'port' : endpoint
.port
,
346 'is_secure' : endpoint
.cert
is not None,
353 'ceph_conf' : '/etc/ceph/ceph.conf',
360 with contextutil
.nested(
361 lambda: download(ctx
=ctx
, config
=config
),
362 lambda: create_users(ctx
=ctx
, config
=dict(
364 ragweed_conf
=ragweed_conf
,
367 run_stages
=run_stages
),
368 lambda: configure(ctx
=ctx
, config
=dict(
370 ragweed_conf
=ragweed_conf
,
372 run_stages
=run_stages
),
373 lambda: run_tests(ctx
=ctx
, config
=config
, run_stages
=run_stages
),