blob: ddfc75d804d524f4aedf98cfd7b657e70f83ce8a [file] [log] [blame]
sslypushenko0de7d052015-04-16 18:49:55 +03001#!/usr/bin/env python
2
3# Copyright 2015 Mirantis, Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
Jane Zadorozhna00fc3dc2015-05-27 18:01:56 +030017"""
18Utility for creating **accounts.yaml** file for concurrent test runs.
19Creates one primary user, one alt user, one swift admin, one stack owner
20and one admin (optionally) for each concurrent thread. The utility creates
21user for each tenant. The **accounts.yaml** file will be valid and contain
22credentials for created users, so each user will be in separate tenant and
23have the username, tenant_name, password and roles.
24
25**Usage:** ``tempest-account-generator [-h] [OPTIONS] accounts_file.yaml``.
26
27Positional Arguments
Matthew Treinishf45ba2e2015-08-24 15:05:01 -040028--------------------
Jane Zadorozhna00fc3dc2015-05-27 18:01:56 +030029**accounts_file.yaml** (Required) Provide an output accounts yaml file. Utility
30creates a .yaml file in the directory where the command is ran. The appropriate
31name for the file is *accounts.yaml* and it should be placed in *tempest/etc*
32directory.
33
34Authentication
35--------------
36
37Account generator creates users and tenants so it needs the admin credentials
38of your cloud to operate properly. The corresponding info can be given either
39through CLI options or environment variables.
40
41You're probably familiar with these, but just to remind::
42
43 +----------+------------------+----------------------+
44 | Param | CLI | Environment Variable |
45 +----------+------------------+----------------------+
46 | Username | --os-username | OS_USERNAME |
47 | Password | --os-password | OS_PASSWORD |
48 | Tenant | --os-tenant-name | OS_TENANT_NAME |
49 +----------+------------------+----------------------+
50
51Optional Arguments
Matthew Treinishf45ba2e2015-08-24 15:05:01 -040052------------------
Jane Zadorozhna00fc3dc2015-05-27 18:01:56 +030053**-h**, **--help** (Optional) Shows help message with the description of
54utility and its arguments, and exits.
55
56**c /etc/tempest.conf**, **--config-file /etc/tempest.conf** (Optional) Path to
57tempest config file.
58
59**--os-username <auth-user-name>** (Optional) Name used for authentication with
60the OpenStack Identity service. Defaults to env[OS_USERNAME]. Note: User should
61have permissions to create new user accounts and tenants.
62
63**--os-password <auth-password>** (Optional) Password used for authentication
64with the OpenStack Identity service. Defaults to env[OS_PASSWORD].
65
66**--os-tenant-name <auth-tenant-name>** (Optional) Tenant to request
67authorization on. Defaults to env[OS_TENANT_NAME].
68
69**--tag TAG** (Optional) Resources tag. Each created resource (user, project)
70will have the prefix with the given TAG in its name. Using tag is recommended
71for the further using, cleaning resources.
72
73**-r CONCURRENCY**, **--concurrency CONCURRENCY** (Required) Concurrency count
74(default: 1). The number of accounts required can be estimated as
75CONCURRENCY x 2. Each user provided in *accounts.yaml* file will be in
76a different tenant. This is required to provide isolation between test for
77running in parallel.
78
79**--with-admin** (Optional) Creates admin for each concurrent group
80(default: False).
81
82To see help on specific argument, please do: ``tempest-account-generator
83[OPTIONS] <accounts_file.yaml> -h``.
84"""
sslypushenko0de7d052015-04-16 18:49:55 +030085import argparse
David Kranz0aa4a7b2015-06-08 13:25:41 -040086import netaddr
sslypushenko0de7d052015-04-16 18:49:55 +030087import os
David Paterson68b8b9d2015-12-01 15:44:14 -080088import traceback
sslypushenko0de7d052015-04-16 18:49:55 +030089
David Paterson68b8b9d2015-12-01 15:44:14 -080090from cliff import command
sslypushenko0de7d052015-04-16 18:49:55 +030091from oslo_log import log as logging
Ken'ichi Ohmichi8844b372016-01-13 00:09:17 +000092import tempest_lib.auth
93from tempest_lib.common.utils import data_utils
94import tempest_lib.exceptions
Ken'ichi Ohmichi5a319512016-01-12 23:58:47 +000095from tempest_lib.services.network import networks_client
96from tempest_lib.services.network import subnets_client
sslypushenko0de7d052015-04-16 18:49:55 +030097import yaml
98
Ken'ichi Ohmichi6ea3f982015-11-09 12:41:13 +000099from tempest.common import identity
sslypushenko0de7d052015-04-16 18:49:55 +0300100from tempest import config
Matthew Treinish36c2e282015-08-25 00:30:15 -0400101from tempest import exceptions as exc
sslypushenko0de7d052015-04-16 18:49:55 +0300102from tempest.services.identity.v2.json import identity_client
Daniel Mellado6b16b922015-12-07 12:43:08 +0000103from tempest.services.identity.v2.json import roles_client
Daniel Melladob04da902015-11-20 17:43:12 +0100104from tempest.services.identity.v2.json import tenants_client
Daniel Mellado82c83a52015-12-09 15:16:49 +0000105from tempest.services.identity.v2.json import users_client
David Kranz0aa4a7b2015-06-08 13:25:41 -0400106from tempest.services.network.json import network_client
sslypushenko0de7d052015-04-16 18:49:55 +0300107
108LOG = None
109CONF = config.CONF
David Paterson68b8b9d2015-12-01 15:44:14 -0800110DESCRIPTION = ('Create accounts.yaml file for concurrent test runs.%s'
111 'One primary user, one alt user, '
112 'one swift admin, one stack owner '
113 'and one admin (optionally) will be created '
114 'for each concurrent thread.' % os.linesep)
sslypushenko0de7d052015-04-16 18:49:55 +0300115
116
117def setup_logging():
118 global LOG
119 logging.setup(CONF, __name__)
120 LOG = logging.getLogger(__name__)
121
122
David Kranz0aa4a7b2015-06-08 13:25:41 -0400123def get_admin_clients(opts):
sslypushenko0de7d052015-04-16 18:49:55 +0300124 _creds = tempest_lib.auth.KeystoneV2Credentials(
125 username=opts.os_username,
126 password=opts.os_password,
127 tenant_name=opts.os_tenant_name)
128 auth_params = {
129 'disable_ssl_certificate_validation':
130 CONF.identity.disable_ssl_certificate_validation,
131 'ca_certs': CONF.identity.ca_certificates_file,
132 'trace_requests': CONF.debug.trace_requests
133 }
134 _auth = tempest_lib.auth.KeystoneV2AuthProvider(
135 _creds, CONF.identity.uri, **auth_params)
136 params = {
137 'disable_ssl_certificate_validation':
138 CONF.identity.disable_ssl_certificate_validation,
139 'ca_certs': CONF.identity.ca_certificates_file,
140 'trace_requests': CONF.debug.trace_requests,
141 'build_interval': CONF.compute.build_interval,
142 'build_timeout': CONF.compute.build_timeout
143 }
Ken'ichi Ohmichia6287072015-07-02 02:43:15 +0000144 identity_admin = identity_client.IdentityClient(
sslypushenko0de7d052015-04-16 18:49:55 +0300145 _auth,
146 CONF.identity.catalog_type,
147 CONF.identity.region,
148 endpoint_type='adminURL',
149 **params
150 )
Daniel Melladob04da902015-11-20 17:43:12 +0100151 tenants_admin = tenants_client.TenantsClient(
152 _auth,
153 CONF.identity.catalog_type,
154 CONF.identity.region,
155 endpoint_type='adminURL',
156 **params
157 )
Daniel Mellado6b16b922015-12-07 12:43:08 +0000158 roles_admin = roles_client.RolesClient(
159 _auth,
160 CONF.identity.catalog_type,
161 CONF.identity.region,
162 endpoint_type='adminURL',
163 **params
164 )
Daniel Mellado82c83a52015-12-09 15:16:49 +0000165 users_admin = users_client.UsersClient(
166 _auth,
167 CONF.identity.catalog_type,
168 CONF.identity.region,
169 endpoint_type='adminURL',
170 **params
171 )
David Kranz0aa4a7b2015-06-08 13:25:41 -0400172 network_admin = None
John Warren94d8faf2015-09-15 12:22:24 -0400173 networks_admin = None
John Warren3961acd2015-10-02 14:38:53 -0400174 subnets_admin = None
John Warren94d8faf2015-09-15 12:22:24 -0400175 neutron_iso_networks = False
David Kranz0aa4a7b2015-06-08 13:25:41 -0400176 if (CONF.service_available.neutron and
177 CONF.auth.create_isolated_networks):
John Warren94d8faf2015-09-15 12:22:24 -0400178 neutron_iso_networks = True
Ken'ichi Ohmichia6287072015-07-02 02:43:15 +0000179 network_admin = network_client.NetworkClient(
David Kranz0aa4a7b2015-06-08 13:25:41 -0400180 _auth,
181 CONF.network.catalog_type,
182 CONF.network.region or CONF.identity.region,
183 endpoint_type='adminURL',
184 **params)
John Warren94d8faf2015-09-15 12:22:24 -0400185 networks_admin = networks_client.NetworksClient(
186 _auth,
187 CONF.network.catalog_type,
188 CONF.network.region or CONF.identity.region,
189 endpoint_type='adminURL',
190 **params)
John Warren3961acd2015-10-02 14:38:53 -0400191 subnets_admin = subnets_client.SubnetsClient(
192 _auth,
193 CONF.network.catalog_type,
194 CONF.network.region or CONF.identity.region,
195 endpoint_type='adminURL',
196 **params)
Daniel Mellado82c83a52015-12-09 15:16:49 +0000197 return (identity_admin, tenants_admin, roles_admin, users_admin,
198 neutron_iso_networks, network_admin, networks_admin, subnets_admin)
sslypushenko0de7d052015-04-16 18:49:55 +0300199
200
201def create_resources(opts, resources):
Daniel Mellado82c83a52015-12-09 15:16:49 +0000202 (identity_admin, tenants_admin, roles_admin, users_admin,
203 neutron_iso_networks, network_admin, networks_admin,
204 subnets_admin) = get_admin_clients(opts)
Daniel Mellado6b16b922015-12-07 12:43:08 +0000205 roles = roles_admin.list_roles()['roles']
sslypushenko0de7d052015-04-16 18:49:55 +0300206 for u in resources['users']:
207 u['role_ids'] = []
208 for r in u.get('roles', ()):
209 try:
210 role = filter(lambda r_: r_['name'] == r, roles)[0]
sslypushenko0de7d052015-04-16 18:49:55 +0300211 except IndexError:
Matthew Treinish36c2e282015-08-25 00:30:15 -0400212 msg = "Role: %s doesn't exist" % r
213 raise exc.InvalidConfiguration(msg)
214 u['role_ids'] += [role['id']]
Daniel Melladob04da902015-11-20 17:43:12 +0100215 existing = [x['name'] for x in tenants_admin.list_tenants()['tenants']]
sslypushenko0de7d052015-04-16 18:49:55 +0300216 for tenant in resources['tenants']:
217 if tenant not in existing:
Daniel Melladob04da902015-11-20 17:43:12 +0100218 tenants_admin.create_tenant(tenant)
sslypushenko0de7d052015-04-16 18:49:55 +0300219 else:
zhangguoqing6c096642016-01-04 06:17:21 +0000220 LOG.warning("Tenant '%s' already exists in this environment"
221 % tenant)
sslypushenko0de7d052015-04-16 18:49:55 +0300222 LOG.info('Tenants created')
223 for u in resources['users']:
224 try:
Daniel Melladob04da902015-11-20 17:43:12 +0100225 tenant = identity.get_tenant_by_name(tenants_admin, u['tenant'])
sslypushenko0de7d052015-04-16 18:49:55 +0300226 except tempest_lib.exceptions.NotFound:
227 LOG.error("Tenant: %s - not found" % u['tenant'])
228 continue
229 while True:
230 try:
Daniel Melladob04da902015-11-20 17:43:12 +0100231 identity.get_user_by_username(tenants_admin,
Ken'ichi Ohmichid9fed312015-11-09 13:05:32 +0000232 tenant['id'], u['name'])
sslypushenko0de7d052015-04-16 18:49:55 +0300233 except tempest_lib.exceptions.NotFound:
Daniel Mellado82c83a52015-12-09 15:16:49 +0000234 users_admin.create_user(
sslypushenko0de7d052015-04-16 18:49:55 +0300235 u['name'], u['pass'], tenant['id'],
236 "%s@%s" % (u['name'], tenant['id']),
237 enabled=True)
238 break
239 else:
zhangguoqing6c096642016-01-04 06:17:21 +0000240 LOG.warning("User '%s' already exists in this environment. "
241 "New name generated" % u['name'])
sslypushenko0de7d052015-04-16 18:49:55 +0300242 u['name'] = random_user_name(opts.tag, u['prefix'])
243
244 LOG.info('Users created')
John Warren94d8faf2015-09-15 12:22:24 -0400245 if neutron_iso_networks:
David Kranz0aa4a7b2015-06-08 13:25:41 -0400246 for u in resources['users']:
Daniel Melladob04da902015-11-20 17:43:12 +0100247 tenant = identity.get_tenant_by_name(tenants_admin, u['tenant'])
John Warren94d8faf2015-09-15 12:22:24 -0400248 network_name, router_name = create_network_resources(
John Warren3961acd2015-10-02 14:38:53 -0400249 network_admin, networks_admin, subnets_admin, tenant['id'],
250 u['name'])
David Kranz0aa4a7b2015-06-08 13:25:41 -0400251 u['network'] = network_name
David Paterson15be99e2015-04-08 21:58:19 -0400252 u['router'] = router_name
David Kranz0aa4a7b2015-06-08 13:25:41 -0400253 LOG.info('Networks created')
sslypushenko0de7d052015-04-16 18:49:55 +0300254 for u in resources['users']:
255 try:
Daniel Melladob04da902015-11-20 17:43:12 +0100256 tenant = identity.get_tenant_by_name(tenants_admin, u['tenant'])
sslypushenko0de7d052015-04-16 18:49:55 +0300257 except tempest_lib.exceptions.NotFound:
258 LOG.error("Tenant: %s - not found" % u['tenant'])
259 continue
260 try:
Daniel Melladob04da902015-11-20 17:43:12 +0100261 user = identity.get_user_by_username(tenants_admin,
Ken'ichi Ohmichid9fed312015-11-09 13:05:32 +0000262 tenant['id'], u['name'])
sslypushenko0de7d052015-04-16 18:49:55 +0300263 except tempest_lib.exceptions.NotFound:
264 LOG.error("User: %s - not found" % u['user'])
265 continue
266 for r in u['role_ids']:
267 try:
Daniel Mellado6b16b922015-12-07 12:43:08 +0000268 roles_admin.assign_user_role(tenant['id'], user['id'], r)
sslypushenko0de7d052015-04-16 18:49:55 +0300269 except tempest_lib.exceptions.Conflict:
270 # don't care if it's already assigned
271 pass
272 LOG.info('Roles assigned')
273 LOG.info('Resources deployed successfully!')
274
275
John Warren94d8faf2015-09-15 12:22:24 -0400276def create_network_resources(network_admin_client, networks_admin_client,
John Warren3961acd2015-10-02 14:38:53 -0400277 subnets_admin_client, tenant_id, name):
David Kranz0aa4a7b2015-06-08 13:25:41 -0400278
279 def _create_network(name):
John Warren94d8faf2015-09-15 12:22:24 -0400280 resp_body = networks_admin_client.create_network(
David Kranz0aa4a7b2015-06-08 13:25:41 -0400281 name=name, tenant_id=tenant_id)
282 return resp_body['network']
283
284 def _create_subnet(subnet_name, network_id):
285 base_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
286 mask_bits = CONF.network.tenant_network_mask_bits
287 for subnet_cidr in base_cidr.subnet(mask_bits):
288 try:
John Warren3961acd2015-10-02 14:38:53 -0400289 resp_body = subnets_admin_client.\
David Kranz0aa4a7b2015-06-08 13:25:41 -0400290 create_subnet(
291 network_id=network_id, cidr=str(subnet_cidr),
292 name=subnet_name,
293 tenant_id=tenant_id,
294 enable_dhcp=True,
295 ip_version=4)
296 break
297 except tempest_lib.exceptions.BadRequest as e:
298 if 'overlaps with another subnet' not in str(e):
299 raise
300 else:
301 message = 'Available CIDR for subnet creation could not be found'
302 raise Exception(message)
303 return resp_body['subnet']
304
305 def _create_router(router_name):
306 external_net_id = dict(
307 network_id=CONF.network.public_network_id)
308 resp_body = network_admin_client.create_router(
309 router_name,
310 external_gateway_info=external_net_id,
311 tenant_id=tenant_id)
312 return resp_body['router']
313
314 def _add_router_interface(router_id, subnet_id):
315 network_admin_client.add_router_interface_with_subnet_id(
316 router_id, subnet_id)
317
318 network_name = name + "-network"
319 network = _create_network(network_name)
320 subnet_name = name + "-subnet"
321 subnet = _create_subnet(subnet_name, network['id'])
322 router_name = name + "-router"
323 router = _create_router(router_name)
324 _add_router_interface(router['id'], subnet['id'])
David Paterson15be99e2015-04-08 21:58:19 -0400325 return network_name, router_name
David Kranz0aa4a7b2015-06-08 13:25:41 -0400326
327
sslypushenko0de7d052015-04-16 18:49:55 +0300328def random_user_name(tag, prefix):
329 if tag:
330 return data_utils.rand_name('-'.join((tag, prefix)))
331 else:
332 return data_utils.rand_name(prefix)
333
334
335def generate_resources(opts):
336 spec = [{'number': 1,
337 'prefix': 'primary',
338 'roles': (CONF.auth.tempest_roles +
339 [CONF.object_storage.operator_role])},
340 {'number': 1,
341 'prefix': 'alt',
342 'roles': (CONF.auth.tempest_roles +
Matthew Treinish36c2e282015-08-25 00:30:15 -0400343 [CONF.object_storage.operator_role])}]
344 if CONF.service_available.swift:
345 spec.append({'number': 1,
Matthew Treinish7b05b342015-09-09 17:14:02 -0400346 'prefix': 'swift_operator',
Matthew Treinish36c2e282015-08-25 00:30:15 -0400347 'roles': (CONF.auth.tempest_roles +
Matthew Treinish7b05b342015-09-09 17:14:02 -0400348 [CONF.object_storage.operator_role])})
349 spec.append({'number': 1,
350 'prefix': 'swift_reseller_admin',
351 'roles': (CONF.auth.tempest_roles +
352 [CONF.object_storage.reseller_admin_role])})
Matthew Treinish36c2e282015-08-25 00:30:15 -0400353 if CONF.service_available.heat:
354 spec.append({'number': 1,
355 'prefix': 'stack_owner',
356 'roles': (CONF.auth.tempest_roles +
357 [CONF.orchestration.stack_owner_role])})
sslypushenko0de7d052015-04-16 18:49:55 +0300358 if opts.admin:
359 spec.append({
360 'number': 1,
361 'prefix': 'admin',
362 'roles': (CONF.auth.tempest_roles +
363 [CONF.identity.admin_role])
364 })
365 resources = {'tenants': [],
366 'users': []}
367 for count in range(opts.concurrency):
368 for user_group in spec:
369 users = [random_user_name(opts.tag, user_group['prefix'])
370 for _ in range(user_group['number'])]
371 for user in users:
372 tenant = '-'.join((user, 'tenant'))
373 resources['tenants'].append(tenant)
374 resources['users'].append({
375 'tenant': tenant,
376 'name': user,
Marc Koderer808e8ec2015-12-16 15:38:46 +0100377 'pass': data_utils.rand_password(),
sslypushenko0de7d052015-04-16 18:49:55 +0300378 'prefix': user_group['prefix'],
379 'roles': user_group['roles']
380 })
381 return resources
382
383
384def dump_accounts(opts, resources):
385 accounts = []
386 for user in resources['users']:
David Kranz0aa4a7b2015-06-08 13:25:41 -0400387 account = {
sslypushenko0de7d052015-04-16 18:49:55 +0300388 'username': user['name'],
389 'tenant_name': user['tenant'],
390 'password': user['pass'],
391 'roles': user['roles']
David Kranz0aa4a7b2015-06-08 13:25:41 -0400392 }
David Patersonbfab6b92016-01-21 15:39:49 -0800393 if 'network' in user or 'router' in user:
David Paterson15be99e2015-04-08 21:58:19 -0400394 account['resources'] = {}
David Kranz0aa4a7b2015-06-08 13:25:41 -0400395 if 'network' in user:
David Paterson15be99e2015-04-08 21:58:19 -0400396 account['resources']['network'] = user['network']
397 if 'router' in user:
398 account['resources']['router'] = user['router']
David Kranz0aa4a7b2015-06-08 13:25:41 -0400399 accounts.append(account)
sslypushenko0de7d052015-04-16 18:49:55 +0300400 if os.path.exists(opts.accounts):
401 os.rename(opts.accounts, '.'.join((opts.accounts, 'bak')))
402 with open(opts.accounts, 'w') as f:
403 yaml.dump(accounts, f, default_flow_style=False)
404 LOG.info('%s generated successfully!' % opts.accounts)
405
406
David Paterson68b8b9d2015-12-01 15:44:14 -0800407def _parser_add_args(parser):
sslypushenko0de7d052015-04-16 18:49:55 +0300408 parser.add_argument('-c', '--config-file',
409 metavar='/etc/tempest.conf',
410 help='path to tempest config file')
411 parser.add_argument('--os-username',
412 metavar='<auth-user-name>',
413 default=os.environ.get('OS_USERNAME'),
Jane Zadorozhna00fc3dc2015-05-27 18:01:56 +0300414 help='User should have permissions '
sslypushenko0de7d052015-04-16 18:49:55 +0300415 'to create new user accounts and '
416 'tenants. Defaults to env[OS_USERNAME].')
417 parser.add_argument('--os-password',
418 metavar='<auth-password>',
419 default=os.environ.get('OS_PASSWORD'),
420 help='Defaults to env[OS_PASSWORD].')
421 parser.add_argument('--os-tenant-name',
422 metavar='<auth-tenant-name>',
423 default=os.environ.get('OS_TENANT_NAME'),
424 help='Defaults to env[OS_TENANT_NAME].')
425 parser.add_argument('--tag',
426 default='',
427 required=False,
428 dest='tag',
429 help='Resources tag')
430 parser.add_argument('-r', '--concurrency',
431 default=1,
432 type=int,
433 required=True,
434 dest='concurrency',
435 help='Concurrency count')
436 parser.add_argument('--with-admin',
437 action='store_true',
438 dest='admin',
Jane Zadorozhna00fc3dc2015-05-27 18:01:56 +0300439 help='Creates admin for each concurrent group')
sslypushenko0de7d052015-04-16 18:49:55 +0300440 parser.add_argument('accounts',
441 metavar='accounts_file.yaml',
442 help='Output accounts yaml file')
443
David Paterson68b8b9d2015-12-01 15:44:14 -0800444
445def get_options():
446 usage_string = ('tempest-account-generator [-h] <ARG> ...\n\n'
447 'To see help on specific argument, do:\n'
448 'tempest-account-generator <ARG> -h')
449 parser = argparse.ArgumentParser(
450 description=DESCRIPTION,
451 formatter_class=argparse.ArgumentDefaultsHelpFormatter,
452 usage=usage_string
453 )
454
455 _parser_add_args(parser)
sslypushenko0de7d052015-04-16 18:49:55 +0300456 opts = parser.parse_args()
sslypushenko0de7d052015-04-16 18:49:55 +0300457 return opts
458
459
David Paterson68b8b9d2015-12-01 15:44:14 -0800460class TempestAccountGenerator(command.Command):
461
462 def get_parser(self, prog_name):
463 parser = super(TempestAccountGenerator, self).get_parser(prog_name)
464 _parser_add_args(parser)
465 return parser
466
467 def take_action(self, parsed_args):
468 try:
469 return main(parsed_args)
470 except Exception:
471 LOG.exception("Failure generating test accounts.")
472 traceback.print_exc()
473 raise
474 return 0
475
476 def get_description(self):
477 return DESCRIPTION
478
479
sslypushenko0de7d052015-04-16 18:49:55 +0300480def main(opts=None):
sslypushenko0de7d052015-04-16 18:49:55 +0300481 setup_logging()
David Paterson68b8b9d2015-12-01 15:44:14 -0800482 if not opts:
483 LOG.warn("Use of: 'tempest-account-generator' is deprecated, "
484 "please use: 'tempest account-generator'")
485 opts = get_options()
486 if opts.config_file:
487 config.CONF.set_config_path(opts.config_file)
sslypushenko0de7d052015-04-16 18:49:55 +0300488 resources = generate_resources(opts)
489 create_resources(opts, resources)
490 dump_accounts(opts, resources)
491
492if __name__ == "__main__":
493 main()