]>
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
]
46 def get_ragweed_dir(testdir
, client
):
47 return '{}/ragweed.{}'.format(testdir
, client
)
49 @contextlib.contextmanager
50 def download(ctx
, config
):
52 Download the s3 tests from the git builder.
53 Remove downloaded s3 file upon exit.
55 The context passed in should be identical to the context
56 passed in to the main task.
58 assert isinstance(config
, dict)
59 log
.info('Downloading ragweed...')
60 testdir
= teuthology
.get_testdir(ctx
)
61 for (client
, cconf
) in config
.items():
62 ragweed_dir
= get_ragweed_dir(testdir
, client
)
63 ragweed_repo
= ctx
.config
.get('ragweed_repo',
64 teuth_config
.ceph_git_base_url
+ 'ragweed.git')
65 for branch
in get_ragweed_branches(ctx
.config
, cconf
):
66 log
.info("Using branch '%s' for ragweed", branch
)
68 ctx
.cluster
.only(client
).sh(
69 script
=f
'git clone -b {branch} {ragweed_repo} {ragweed_dir}')
71 except Exception as e
:
76 sha1
= cconf
.get('sha1')
78 ctx
.cluster
.only(client
).run(
82 'git', 'reset', '--hard', sha1
,
88 log
.info('Removing ragweed...')
90 ragweed_dir
= get_ragweed_dir(testdir
, client
)
91 ctx
.cluster
.only(client
).run(
92 args
=['rm', '-rf', ragweed_dir
]
96 def _config_user(ragweed_conf
, section
, user
):
98 Configure users for this section by stashing away keys, ids, and
101 ragweed_conf
[section
].setdefault('user_id', user
)
102 ragweed_conf
[section
].setdefault('email', '{user}+test@test.test'.format(user
=user
))
103 ragweed_conf
[section
].setdefault('display_name', 'Mr. {user}'.format(user
=user
))
104 ragweed_conf
[section
].setdefault('access_key', ''.join(random
.choice(string
.ascii_uppercase
) for i
in range(20)))
105 ragweed_conf
[section
].setdefault('secret_key', base64
.b64encode(os
.urandom(40)).decode('ascii'))
108 @contextlib.contextmanager
109 def create_users(ctx
, config
, run_stages
):
111 Create a main and an alternate s3 user.
113 assert isinstance(config
, dict)
115 for client
, properties
in config
['config'].items():
116 run_stages
[client
] = properties
.get('stages', 'prepare,check').split(',')
118 log
.info('Creating rgw users...')
119 testdir
= teuthology
.get_testdir(ctx
)
120 users
= {'user regular': 'ragweed', 'user system': 'sysuser'}
121 for client
in config
['clients']:
122 if not 'prepare' in run_stages
[client
]:
123 # should have been prepared in a previous run
126 ragweed_conf
= config
['ragweed_conf'][client
]
127 ragweed_conf
.setdefault('fixtures', {})
128 ragweed_conf
['rgw'].setdefault('bucket_prefix', 'test-' + client
)
129 for section
, user
in users
.items():
130 _config_user(ragweed_conf
, section
, '{user}.{client}'.format(user
=user
, client
=client
))
131 log
.debug('Creating user {user} on {host}'.format(user
=ragweed_conf
[section
]['user_id'], host
=client
))
132 if user
== 'sysuser':
136 ctx
.cluster
.only(client
).run(
140 '{tdir}/archive/coverage'.format(tdir
=testdir
),
144 '--uid', ragweed_conf
[section
]['user_id'],
145 '--display-name', ragweed_conf
[section
]['display_name'],
146 '--access-key', ragweed_conf
[section
]['access_key'],
147 '--secret', ragweed_conf
[section
]['secret_key'],
148 '--email', ragweed_conf
[section
]['email'],
155 for client
in config
['clients']:
156 if not 'check' in run_stages
[client
]:
157 # only remove user if went through the check stage
159 for user
in users
.values():
160 uid
= '{user}.{client}'.format(user
=user
, client
=client
)
161 ctx
.cluster
.only(client
).run(
165 '{tdir}/archive/coverage'.format(tdir
=testdir
),
175 @contextlib.contextmanager
176 def configure(ctx
, config
, run_stages
):
178 Configure the local config files.
180 assert isinstance(config
, dict)
181 log
.info('Configuring ragweed...')
182 testdir
= teuthology
.get_testdir(ctx
)
183 for client
, properties
in config
['clients'].items():
184 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
185 preparing
= 'prepare' in run_stages
[client
]
187 # should have been prepared in a previous run
190 ragweed_conf
= config
['ragweed_conf'][client
]
191 if properties
is not None and 'slow_backend' in properties
:
192 ragweed_conf
['fixtures']['slow backend'] = properties
['slow_backend']
195 ragweed_conf
.write(conf_fp
)
197 path
='{tdir}/archive/ragweed.{client}.conf'.format(tdir
=testdir
, client
=client
),
198 data
=conf_fp
.getvalue(),
201 log
.info('Configuring boto...')
202 boto_src
= os
.path
.join(os
.path
.dirname(__file__
), 'boto.cfg.template')
203 for client
, properties
in config
['clients'].items():
204 with
open(boto_src
, 'r') as f
:
205 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
206 conf
= f
.read().format(
207 idle_timeout
=config
.get('idle_timeout', 30)
209 remote
.write_file('{tdir}/boto.cfg'.format(tdir
=testdir
), conf
)
215 log
.info('Cleaning up boto...')
216 for client
, properties
in config
['clients'].items():
217 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
221 '{tdir}/boto.cfg'.format(tdir
=testdir
),
225 def get_toxvenv_dir(ctx
):
226 return ctx
.tox
.venv_path
228 def toxvenv_sh(ctx
, remote
, args
, **kwargs
):
229 activate
= get_toxvenv_dir(ctx
) + '/bin/activate'
230 return remote
.sh(['source', activate
, run
.Raw('&&')] + args
, **kwargs
)
232 @contextlib.contextmanager
233 def run_tests(ctx
, config
, run_stages
):
235 Run the ragweed after everything is set up.
237 :param ctx: Context passed to task
238 :param config: specific configuration information
240 assert isinstance(config
, dict)
241 testdir
= teuthology
.get_testdir(ctx
)
242 attrs
= ["not fails_on_rgw"]
243 for client
, client_config
in config
.items():
244 ragweed_dir
= get_ragweed_dir(testdir
, client
)
245 stages
= ','.join(run_stages
[client
])
247 'cd', ragweed_dir
, run
.Raw('&&'),
248 'RAGWEED_CONF={tdir}/archive/ragweed.{client}.conf'.format(tdir
=testdir
, client
=client
),
249 'RAGWEED_STAGES={stages}'.format(stages
=stages
),
250 'BOTO_CONFIG={tdir}/boto.cfg'.format(tdir
=testdir
),
255 '-m', ' and '.join(attrs
),
257 if client_config
is not None and 'extra_args' in client_config
:
258 args
.extend(client_config
['extra_args'])
260 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
261 toxvenv_sh(ctx
, remote
, args
, label
="ragweed tests against rgw")
264 @contextlib.contextmanager
265 def task(ctx
, config
):
267 Run the ragweed suite against rgw.
269 To run all tests on all clients::
276 To restrict testing to particular clients::
281 - ragweed: [client.0]
283 To run against a server on client.1 and increase the boto timeout to 10m::
292 stages: prepare,check
294 To pass extra arguments to nose (e.g. to run a certain test)::
301 extra_args: ['test_s3:test_object_acl_grand_public_read']
303 extra_args: ['--exclude', 'test_100_continue']
305 assert hasattr(ctx
, 'rgw'), 'ragweed must run after the rgw task'
306 assert hasattr(ctx
, 'tox'), 'ragweed must run after the tox task'
307 assert config
is None or isinstance(config
, list) \
308 or isinstance(config
, dict), \
309 "task ragweed only supports a list or dictionary for configuration"
310 all_clients
= ['client.{id}'.format(id=id_
)
311 for id_
in teuthology
.all_roles_of_type(ctx
.cluster
, 'client')]
314 if isinstance(config
, list):
315 config
= dict.fromkeys(config
)
316 clients
= config
.keys()
318 overrides
= ctx
.config
.get('overrides', {})
319 # merge each client section, not the top level.
320 for client
in config
.keys():
321 if not config
[client
]:
323 teuthology
.deep_merge(config
[client
], overrides
.get('ragweed', {}))
325 log
.debug('ragweed config is %s', config
)
328 for client
in clients
:
329 # use rgw_server endpoint if given, or default to same client
330 target
= config
[client
].get('rgw_server', client
)
332 endpoint
= ctx
.rgw
.role_endpoints
.get(target
)
333 assert endpoint
, 'ragweed: no rgw endpoint for {}'.format(target
)
335 ragweed_conf
[client
] = ConfigObj(
340 'host' : endpoint
.dns_name
,
341 'port' : endpoint
.port
,
342 'is_secure' : endpoint
.cert
is not None,
349 'ceph_conf' : '/etc/ceph/ceph.conf',
356 with contextutil
.nested(
357 lambda: download(ctx
=ctx
, config
=config
),
358 lambda: create_users(ctx
=ctx
, config
=dict(
360 ragweed_conf
=ragweed_conf
,
363 run_stages
=run_stages
),
364 lambda: configure(ctx
=ctx
, config
=dict(
366 ragweed_conf
=ragweed_conf
,
368 run_stages
=run_stages
),
369 lambda: run_tests(ctx
=ctx
, config
=config
, run_stages
=run_stages
),