4 from cStringIO import StringIO
5 from configobj import ConfigObj
11 from teuthology import misc as teuthology
12 from teuthology import contextutil
13 from teuthology.config import config as teuth_config
14 from teuthology.orchestra import run
15 from teuthology.orchestra.connection import split_user
17 log = logging.getLogger(__name__)
20 @contextlib.contextmanager
21 def download(ctx, config):
23 Download the Swift API.
25 testdir = teuthology.get_testdir(ctx)
26 assert isinstance(config, list)
27 log.info('Downloading swift...')
29 ctx.cluster.only(client).run(
32 teuth_config.ceph_git_base_url + 'swift.git',
33 '{tdir}/swift'.format(tdir=testdir),
39 log.info('Removing swift...')
40 testdir = teuthology.get_testdir(ctx)
42 ctx.cluster.only(client).run(
46 '{tdir}/swift'.format(tdir=testdir),
50 def _config_user(testswift_conf, account, user, suffix):
52 Configure a swift user
54 :param account: Swift account
55 :param user: User name
56 :param suffix: user name and email suffixes.
58 testswift_conf['func_test'].setdefault('account{s}'.format(s=suffix), account)
59 testswift_conf['func_test'].setdefault('username{s}'.format(s=suffix), user)
60 testswift_conf['func_test'].setdefault('email{s}'.format(s=suffix), '{account}+test@test.test'.format(account=account))
61 testswift_conf['func_test'].setdefault('display_name{s}'.format(s=suffix), 'Mr. {account} {user}'.format(account=account, user=user))
62 testswift_conf['func_test'].setdefault('password{s}'.format(s=suffix), base64.b64encode(os.urandom(40)))
64 @contextlib.contextmanager
65 def create_users(ctx, config):
67 Create rgw users to interact with the swift interface.
69 assert isinstance(config, dict)
70 log.info('Creating rgw users...')
71 testdir = teuthology.get_testdir(ctx)
72 users = {'': 'foo', '2': 'bar'}
73 for client in config['clients']:
74 cluster_name, daemon_type, client_id = teuthology.split_role(client)
75 testswift_conf = config['testswift_conf'][client]
76 for suffix, user in users.iteritems():
77 _config_user(testswift_conf, '{user}.{client}'.format(user=user, client=client), user, suffix)
78 ctx.cluster.only(client).run(
82 '{tdir}/archive/coverage'.format(tdir=testdir),
85 '--cluster', cluster_name,
87 '--subuser', '{account}:{user}'.format(account=testswift_conf['func_test']['account{s}'.format(s=suffix)],user=user),
88 '--display-name', testswift_conf['func_test']['display_name{s}'.format(s=suffix)],
89 '--secret', testswift_conf['func_test']['password{s}'.format(s=suffix)],
90 '--email', testswift_conf['func_test']['email{s}'.format(s=suffix)],
91 '--key-type', 'swift',
98 for client in config['clients']:
99 for user in users.itervalues():
100 uid = '{user}.{client}'.format(user=user, client=client)
101 cluster_name, daemon_type, client_id = teuthology.split_role(client)
102 ctx.cluster.only(client).run(
106 '{tdir}/archive/coverage'.format(tdir=testdir),
109 '--cluster', cluster_name,
116 @contextlib.contextmanager
117 def configure(ctx, config):
119 Configure rgw and Swift
121 assert isinstance(config, dict)
122 log.info('Configuring testswift...')
123 testdir = teuthology.get_testdir(ctx)
124 for client, properties in config['clients'].iteritems():
125 log.info('client={c}'.format(c=client))
126 log.info('config={c}'.format(c=config))
127 testswift_conf = config['testswift_conf'][client]
128 if properties is not None and 'rgw_server' in properties:
130 for target, roles in zip(ctx.config['targets'].iterkeys(), ctx.config['roles']):
131 log.info('roles: ' + str(roles))
132 log.info('target: ' + str(target))
133 if properties['rgw_server'] in roles:
134 _, host = split_user(target)
135 assert host is not None, "Invalid client specified as the rgw_server"
136 testswift_conf['func_test']['auth_host'] = host
138 testswift_conf['func_test']['auth_host'] = 'localhost'
141 (remote,) = ctx.cluster.only(client).remotes.keys()
145 '{tdir}/swift'.format(tdir=testdir),
151 testswift_conf.write(conf_fp)
152 teuthology.write_file(
154 path='{tdir}/archive/testswift.{client}.conf'.format(tdir=testdir, client=client),
155 data=conf_fp.getvalue(),
160 @contextlib.contextmanager
161 def run_tests(ctx, config):
163 Run an individual Swift test.
165 assert isinstance(config, dict)
166 testdir = teuthology.get_testdir(ctx)
167 for client, client_config in config.iteritems():
169 'SWIFT_TEST_CONFIG_FILE={tdir}/archive/testswift.{client}.conf'.format(tdir=testdir, client=client),
170 '{tdir}/swift/virtualenv/bin/nosetests'.format(tdir=testdir),
172 '{tdir}/swift/test/functional'.format(tdir=testdir),
174 '-a', '!fails_on_rgw',
176 if client_config is not None and 'extra_args' in client_config:
177 args.extend(client_config['extra_args'])
179 ctx.cluster.only(client).run(
184 @contextlib.contextmanager
185 def task(ctx, config):
187 Run the testswift suite against rgw.
189 To run all tests on all clients::
196 To restrict testing to particular clients::
201 - testswift: [client.0]
203 To run against a server on client.1::
212 To pass extra arguments to nose (e.g. to run a certain test)::
219 extra_args: ['test.functional.tests:TestFileUTF8', '-m', 'testCopy']
221 extra_args: ['--exclude', 'TestFile']
223 assert config is None or isinstance(config, list) \
224 or isinstance(config, dict), \
225 "task testswift only supports a list or dictionary for configuration"
226 all_clients = ['client.{id}'.format(id=id_)
227 for id_ in teuthology.all_roles_of_type(ctx.cluster, 'client')]
230 if isinstance(config, list):
231 config = dict.fromkeys(config)
232 clients = config.keys()
234 log.info('clients={c}'.format(c=clients))
237 for client in clients:
238 testswift_conf[client] = ConfigObj(
245 'auth_prefix' : '/auth/',
250 with contextutil.nested(
251 lambda: download(ctx=ctx, config=clients),
252 lambda: create_users(ctx=ctx, config=dict(
254 testswift_conf=testswift_conf,
256 lambda: configure(ctx=ctx, config=dict(
258 testswift_conf=testswift_conf,
260 lambda: run_tests(ctx=ctx, config=config),