]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/tempest.py
8550f9b90f2c06e19a63ff09f06a22f2c3807c39
2 Deploy and configure Tempest for Teuthology
7 from teuthology
import misc
as teuthology
8 from teuthology
import contextutil
9 from teuthology
.exceptions
import ConfigError
10 from teuthology
.orchestra
import run
12 log
= logging
.getLogger(__name__
)
15 def get_tempest_dir(ctx
):
16 return '{tdir}/tempest'.format(tdir
=teuthology
.get_testdir(ctx
))
18 def run_in_tempest_dir(ctx
, client
, cmdargs
, **kwargs
):
19 ctx
.cluster
.only(client
).run(
20 args
=[ 'cd', get_tempest_dir(ctx
), run
.Raw('&&'), ] + cmdargs
,
24 def run_in_tempest_rgw_dir(ctx
, client
, cmdargs
, **kwargs
):
25 ctx
.cluster
.only(client
).run(
26 args
=[ 'cd', get_tempest_dir(ctx
) + '/rgw', run
.Raw('&&'), ] + cmdargs
,
30 def run_in_tempest_venv(ctx
, client
, cmdargs
, **kwargs
):
31 run_in_tempest_dir(ctx
, client
,
33 '.tox/venv/bin/activate',
35 ] + cmdargs
, **kwargs
)
37 @contextlib.contextmanager
38 def download(ctx
, config
):
40 Download the Tempest from github.
41 Remove downloaded file upon exit.
43 The context passed in should be identical to the context
44 passed in to the main task.
46 assert isinstance(config
, dict)
47 log
.info('Downloading Tempest...')
48 for (client
, cconf
) in config
.items():
49 ctx
.cluster
.only(client
).run(
52 '-b', cconf
.get('force-branch', 'master'),
53 'https://github.com/openstack/tempest.git',
58 sha1
= cconf
.get('sha1')
60 run_in_tempest_dir(ctx
, client
, [ 'git', 'reset', '--hard', sha1
])
62 # tox.ini contains a dead link, replace it with the new one
63 from_url
= 'https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt'
64 to_url
= 'https://opendev.org/openstack/requirements/raw/branch/stable/pike/upper-constraints.txt'
65 run_in_tempest_dir(ctx
, client
, [
67 run
.Raw('"s|{}|{}|"'.format(from_url
, to_url
)),
73 log
.info('Removing Tempest...')
75 ctx
.cluster
.only(client
).run(
76 args
=[ 'rm', '-rf', get_tempest_dir(ctx
) ],
79 def get_toxvenv_dir(ctx
):
80 return ctx
.tox
.venv_path
82 @contextlib.contextmanager
83 def setup_venv(ctx
, config
):
85 Setup the virtualenv for Tempest using tox.
87 assert isinstance(config
, dict)
88 log
.info('Setting up virtualenv for Tempest')
89 for (client
, _
) in config
.items():
90 run_in_tempest_dir(ctx
, client
,
91 [ '{tvdir}/bin/tox'.format(tvdir
=get_toxvenv_dir(ctx
)),
92 '-e', 'venv', '--notest'
96 def setup_logging(ctx
, cpar
):
97 cpar
.set('DEFAULT', 'log_dir', teuthology
.get_archive_dir(ctx
))
98 cpar
.set('DEFAULT', 'log_file', 'tempest.log')
100 def to_config(config
, params
, section
, cpar
):
101 for (k
, v
) in config
[section
].items():
102 if (isinstance(v
, str)):
103 v
= v
.format(**params
)
104 cpar
.set(section
, k
, v
)
106 @contextlib.contextmanager
107 def configure_instance(ctx
, config
):
108 assert isinstance(config
, dict)
109 log
.info('Configuring Tempest')
112 for (client
, cconfig
) in config
.items():
113 run_in_tempest_venv(ctx
, client
,
118 get_tempest_dir(ctx
) + '/workspace.yaml',
122 # prepare the config file
123 tetcdir
= '{tdir}/rgw/etc'.format(tdir
=get_tempest_dir(ctx
))
124 (remote
,) = ctx
.cluster
.only(client
).remotes
.keys()
125 local_conf
= remote
.get_file(tetcdir
+ '/tempest.conf.sample')
127 # fill the params dictionary which allows to use templatized configs
128 keystone_role
= cconfig
.get('use-keystone-role', None)
129 if keystone_role
is None \
130 or keystone_role
not in ctx
.keystone
.public_endpoints
:
131 raise ConfigError('the use-keystone-role is misconfigured')
132 public_host
, public_port
= ctx
.keystone
.public_endpoints
[keystone_role
]
134 'keystone_public_host': public_host
,
135 'keystone_public_port': str(public_port
),
138 cpar
= ConfigParser
.ConfigParser()
139 cpar
.read(local_conf
)
140 setup_logging(ctx
, cpar
)
141 to_config(cconfig
, params
, 'auth', cpar
)
142 to_config(cconfig
, params
, 'identity', cpar
)
143 to_config(cconfig
, params
, 'object-storage', cpar
)
144 to_config(cconfig
, params
, 'object-storage-feature-enabled', cpar
)
145 cpar
.write(open(local_conf
, 'w+'))
147 remote
.put_file(local_conf
, tetcdir
+ '/tempest.conf')
150 @contextlib.contextmanager
151 def run_tempest(ctx
, config
):
152 assert isinstance(config
, dict)
153 log
.info('Configuring Tempest')
155 for (client
, cconf
) in config
.items():
156 blacklist
= cconf
.get('blacklist', [])
157 assert isinstance(blacklist
, list)
158 run_in_tempest_venv(ctx
, client
,
163 get_tempest_dir(ctx
) + '/workspace.yaml',
167 '(tempest.api.object_storage)' +
168 ''.join([ '(?!{blackitem})'.format(blackitem
=blackitem
)
169 for blackitem
in blacklist
])
177 @contextlib.contextmanager
178 def task(ctx
, config
):
180 Deploy and run Tempest's object storage campaign
182 Example of configuration:
188 rgw keystone admin token: ADMIN
189 rgw keystone accepted roles: admin,Member
190 rgw keystone implicit tenants: true
191 rgw keystone accepted admin roles: admin
192 rgw swift enforce content length: true
193 rgw swift account in url: true
194 rgw swift versioning enabled: true
196 # typically, the task should be preceded with install, ceph, tox,
197 # keystone and rgw. Tox and Keystone are specific requirements
200 # it's important to match the prefix with the endpoint's URL
201 # in Keystone. Additionally, if we want to test /info and its
202 # accompanying stuff, the whole Swift API must be put in root
203 # of the whole URL hierarchy (read: frontend_prefix == /swift).
204 frontend_prefix: /swift
206 use-keystone-role: client.0
210 use-keystone-role: client.0
212 admin_username: admin
213 admin_project_name: admin
214 admin_password: ADMIN
215 admin_domain_name: Default
217 uri: http://{keystone_public_host}:{keystone_public_port}/v2.0/
218 uri_v3: http://{keystone_public_host}:{keystone_public_port}/v3/
221 reseller_admin_role: admin
222 object-storage-feature-enabled:
223 container_sync: false
224 discoverability: false
226 # please strip half of these items after merging PRs #15369
228 - .*test_list_containers_reverse_order.*
229 - .*test_list_container_contents_with_end_marker.*
230 - .*test_delete_non_empty_container.*
231 - .*test_container_synchronization.*
232 - .*test_get_object_after_expiration_time.*
233 - .*test_create_object_with_transfer_encoding.*
235 assert config
is None or isinstance(config
, list) \
236 or isinstance(config
, dict), \
237 'task tempest only supports a list or dictionary for configuration'
240 raise ConfigError('tempest must run after the tox task')
242 raise ConfigError('tempest must run after the keystone task')
244 all_clients
= ['client.{id}'.format(id=id_
)
245 for id_
in teuthology
.all_roles_of_type(ctx
.cluster
, 'client')]
248 if isinstance(config
, list):
249 config
= dict.fromkeys(config
)
251 overrides
= ctx
.config
.get('overrides', {})
252 # merge each client section, not the top level.
253 for client
in config
.keys():
254 if not config
[client
]:
256 teuthology
.deep_merge(config
[client
], overrides
.get('keystone', {}))
258 log
.debug('Tempest config is %s', config
)
260 with contextutil
.nested(
261 lambda: download(ctx
=ctx
, config
=config
),
262 lambda: setup_venv(ctx
=ctx
, config
=config
),
263 lambda: configure_instance(ctx
=ctx
, config
=config
),
264 lambda: run_tempest(ctx
=ctx
, config
=config
),