From afe1ad3010590c14abee1c3a8b0b9eb5b519a675 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Wed, 19 Jul 2017 14:20:05 +0000 Subject: [PATCH] qa, rgw: Keystone's instances can be now accessed via non-local network interfaces. Signed-off-by: Radoslaw Zarzynski --- qa/suites/rgw/verify/tasks/rgw_tempest.yaml | 13 +--- qa/tasks/keystone.py | 85 ++++++++++++++------- qa/tasks/rgw.py | 21 ++++- qa/tasks/tempest.py | 57 +++++++------- 4 files changed, 110 insertions(+), 66 deletions(-) diff --git a/qa/suites/rgw/verify/tasks/rgw_tempest.yaml b/qa/suites/rgw/verify/tasks/rgw_tempest.yaml index c86a8ea021e..982999a0cd6 100644 --- a/qa/suites/rgw/verify/tasks/rgw_tempest.yaml +++ b/qa/suites/rgw/verify/tasks/rgw_tempest.yaml @@ -26,27 +26,23 @@ tasks: - name: swift type: object-store description: Swift Service - endpoints: - - service: keystone - publicurl: http://127.0.1:$(public_port)s/v2.0 - - service: swift - publicurl: http://127.0.0.1:7280/v1/KEY_$(tenant_id)s - rgw: frontend_prefix: /swift client.0: valgrind: [--tool=memcheck] - extra_params: --rgw_keystone_url=http://localhost:35357 + use-keystone-role: client.0 - tempest: client.0: force-branch: master + use-keystone-role: client.0 auth: admin_username: admin admin_project_name: admin admin_password: ADMIN admin_domain_name: Default identity: - uri: http://127.0.0.1:5000/v2.0/ - uri_v3: http://127.0.0.1:5000/v3/ + uri: http://{keystone_public_host}:{keystone_public_port}/v2.0/ + uri_v3: http://{keystone_public_host}:{keystone_public_port}/v3/ admin_role: admin object-storage: reseller_admin_role: admin @@ -70,7 +66,6 @@ overrides: osd_min_pg_log_entries: 10 osd_max_pg_log_entries: 10 client: - rgw keystone url: http://localhost:35357 rgw keystone admin token: ADMIN rgw keystone accepted roles: admin,Member rgw keystone implicit tenants: true diff --git a/qa/tasks/keystone.py b/qa/tasks/keystone.py index 76cc1a11520..7dcffe1268a 100644 --- a/qa/tasks/keystone.py +++ b/qa/tasks/keystone.py @@ -1,6 +1,7 @@ """ Deploy and configure Keystone for Teuthology """ +import argparse import contextlib import logging @@ -178,8 +179,9 @@ def run_keystone(ctx, config): client_public_with_id = 'keystone.public' + '.' + client_id client_public_with_cluster = cluster_name + '.' + client_public_with_id + public_host, public_port = ctx.keystone.public_endpoints[client] run_cmd = get_keystone_venved_cmd(ctx, 'keystone-wsgi-public', - [ '--host', 'localhost', '--port', '5000', + [ '--host', public_host, '--port', str(public_port), # Let's put the Keystone in background, wait for EOF # and after receiving it, send SIGTERM to the daemon. # This crazy hack is because Keystone, in contrast to @@ -202,8 +204,9 @@ def run_keystone(ctx, config): # start the admin endpoint client_admin_with_id = 'keystone.admin' + '.' + client_id + admin_host, admin_port = ctx.keystone.admin_endpoints[client] run_cmd = get_keystone_venved_cmd(ctx, 'keystone-wsgi-admin', - [ '--host', 'localhost', '--port', '35357', + [ '--host', admin_host, '--port', str(admin_port), run.Raw('& { read; kill %1; }') ] ) @@ -252,9 +255,12 @@ def dict_to_args(special, items): def run_section_cmds(ctx, cclient, section_cmd, special, section_config_list): + admin_host, admin_port = ctx.keystone.admin_endpoints[cclient] + auth_section = [ ( 'os-token', 'ADMIN' ), - ( 'os-url', 'http://127.0.0.1:35357/v2.0' ), + ( 'os-url', 'http://{host}:{port}/v2.0'.format(host=admin_host, + port=admin_port) ), ] for section_item in section_config_list: @@ -262,36 +268,58 @@ def run_section_cmds(ctx, cclient, section_cmd, special, [ 'openstack' ] + section_cmd.split() + dict_to_args(special, auth_section + section_item.items())) +def create_endpoint(ctx, cclient, service, url): + endpoint_section = { + 'service': service, + 'publicurl': url, + } + return run_section_cmds(ctx, cclient, 'endpoint create', 'service', + [ endpoint_section ]) + @contextlib.contextmanager -def create_users(ctx, config): - """ - Create a main and an alternate s3 user. - """ +def fill_keystone(ctx, config): assert isinstance(config, dict) - (cclient, cconfig) = config.items()[0] + for (cclient, cconfig) in config.items(): + # configure tenants/projects + run_section_cmds(ctx, cclient, 'project create', 'name', + cconfig['tenants']) + run_section_cmds(ctx, cclient, 'user create', 'name', + cconfig['users']) + run_section_cmds(ctx, cclient, 'role create', 'name', + cconfig['roles']) + run_section_cmds(ctx, cclient, 'role add', 'name', + cconfig['role-mappings']) + run_section_cmds(ctx, cclient, 'service create', 'name', + cconfig['services']) - # configure tenants/projects - run_section_cmds(ctx, cclient, 'project create', 'name', - cconfig['tenants']) - run_section_cmds(ctx, cclient, 'user create', 'name', - cconfig['users']) - run_section_cmds(ctx, cclient, 'role create', 'name', - cconfig['roles']) - run_section_cmds(ctx, cclient, 'role add', 'name', - cconfig['role-mappings']) - run_section_cmds(ctx, cclient, 'service create', 'name', - cconfig['services']) - run_section_cmds(ctx, cclient, 'endpoint create', 'service', - cconfig['endpoints']) + public_host, public_port = ctx.keystone.public_endpoints[cclient] + url = 'http://{host}:{port}/v2.0'.format(host=public_host, + port=public_port) + create_endpoint(ctx, cclient, 'keystone', url) + # for the deferred endpoint creation; currently it's used in rgw.py + ctx.keystone.create_endpoint = create_endpoint - # sleep driven synchronization -- just in case - run_in_keystone_venv(ctx, cclient, [ 'sleep', '3' ]) + # sleep driven synchronization -- just in case + run_in_keystone_venv(ctx, cclient, [ 'sleep', '3' ]) try: yield finally: pass +def assign_ports(ctx, config, initial_port): + """ + Assign port numbers starting from @initial_port + """ + port = initial_port + role_endpoints = {} + for remote, roles_for_host in ctx.cluster.remotes.iteritems(): + for role in roles_for_host: + if role in config: + role_endpoints[role] = (remote.name.split('@')[1], port) + port += 1 + + return role_endpoints @contextlib.contextmanager def task(ctx, config): @@ -326,11 +354,6 @@ def task(ctx, config): - name: swift type: object-store description: Swift Service - endpoints: - - service: keystone - publicurl: http://127.0.0.1:$(public_port)s/v2.0 - - service: swift - publicurl: http://127.0.0.1:8000/v1/KEY_$(tenant_id)s """ assert config is None or isinstance(config, list) \ or isinstance(config, dict), \ @@ -348,12 +371,16 @@ def task(ctx, config): log.debug('Keystone config is %s', config) + ctx.keystone = argparse.Namespace() + ctx.keystone.public_endpoints = assign_ports(ctx, config, 5000) + ctx.keystone.admin_endpoints = assign_ports(ctx, config, 35357) + with contextutil.nested( lambda: install_packages(ctx=ctx, config=config), lambda: download(ctx=ctx, config=config), lambda: setup_venv(ctx=ctx, config=config), lambda: configure_instance(ctx=ctx, config=config), lambda: run_keystone(ctx=ctx, config=config), - lambda: create_users(ctx=ctx, config=config), + lambda: fill_keystone(ctx=ctx, config=config), ): yield diff --git a/qa/tasks/rgw.py b/qa/tasks/rgw.py index 9c9012cb436..6d82610ff12 100644 --- a/qa/tasks/rgw.py +++ b/qa/tasks/rgw.py @@ -65,7 +65,26 @@ def start_rgw(ctx, config, clients): '/var/log/ceph/rgw.{client_with_cluster}.log'.format(client_with_cluster=client_with_cluster), '--rgw_ops_log_socket_path', '{tdir}/rgw.opslog.{client_with_cluster}.sock'.format(tdir=testdir, - client_with_cluster=client_with_cluster), + client_with_cluster=client_with_cluster) + ]) + + keystone_role = client_config.get('use-keystone-role', None) + if keystone_role is not None: + if not ctx.keystone: + raise ConfigError('rgw must run after the keystone task') + url = 'http://{host}:{port}/v1/KEY_$(tenant_id)s'.format(host=host, + port=port) + ctx.keystone.create_endpoint(ctx, keystone_role, 'swift', url) + + keystone_host, keystone_port = \ + ctx.keystone.public_endpoints[keystone_role] + rgw_cmd.extend([ + '--rgw_keystone_url', + 'http://{khost}:{kport}'.format(khost=keystone_host, + kport=keystone_port), + ]) + + rgw_cmd.extend([ '--foreground', run.Raw('|'), 'sudo', diff --git a/qa/tasks/tempest.py b/qa/tasks/tempest.py index 0b05dba84df..14cd2ed4a90 100644 --- a/qa/tasks/tempest.py +++ b/qa/tasks/tempest.py @@ -45,31 +45,17 @@ def download(ctx, config): """ assert isinstance(config, dict) log.info('Downloading Tempest...') - s3_branches = [ 'giant', 'firefly', 'firefly-original', 'hammer' ] for (client, cconf) in config.items(): - branch = cconf.get('force-branch', None) - if not branch: - ceph_branch = ctx.config.get('branch') - suite_branch = ctx.config.get('suite_branch', ceph_branch) - if suite_branch in s3_branches: - branch = cconf.get('branch', suite_branch) - else: - branch = cconf.get('branch', 'ceph-' + suite_branch) - if not branch: - raise ValueError( - "Could not determine what branch to use for Tempest!") - else: - log.info("Using branch '%s' for Tempest", branch) - - sha1 = cconf.get('sha1') ctx.cluster.only(client).run( args=[ 'git', 'clone', - '-b', branch, + '-b', cconf.get('force-branch', 'master'), 'https://github.com/openstack/tempest.git', get_tempest_dir(ctx) - ], - ) + ], + ) + + sha1 = cconf.get('sha1') if sha1 is not None: run_in_tempest_dir(ctx, client, [ 'git', 'reset', '--hard', sha1 ]) try: @@ -102,8 +88,10 @@ def setup_logging(ctx, cpar): cpar.set('DEFAULT', 'log_dir', teuthology.get_archive_dir(ctx)) cpar.set('DEFAULT', 'log_file', 'tempest.log') -def to_config(config, section, cpar): +def to_config(config, params, section, cpar): for (k, v) in config[section].items(): + if (isinstance(v, str)): + v = v.format(**params) cpar.set(section, k, v) @contextlib.contextmanager @@ -127,13 +115,24 @@ def configure_instance(ctx, config): (remote,) = ctx.cluster.only(client).remotes.keys() local_conf = remote.get_file(tetcdir + '/tempest.conf.sample') + # fill the params dictionary which allows to use templatized configs + keystone_role = cconfig.get('use-keystone-role', None) + if keystone_role is None \ + or keystone_role not in ctx.keystone.public_endpoints: + raise ConfigError('the use-keystone-role is misconfigured') + public_host, public_port = ctx.keystone.public_endpoints[keystone_role] + params = { + 'keystone_public_host': public_host, + 'keystone_public_port': str(public_port), + } + cpar = ConfigParser.ConfigParser() cpar.read(local_conf) setup_logging(ctx, cpar) - to_config(cconfig, 'auth', cpar) - to_config(cconfig, 'identity', cpar) - to_config(cconfig, 'object-storage', cpar) - to_config(cconfig, 'object-storage-feature-enabled', cpar) + to_config(cconfig, params, 'auth', cpar) + to_config(cconfig, params, 'identity', cpar) + to_config(cconfig, params, 'object-storage', cpar) + to_config(cconfig, params, 'object-storage-feature-enabled', cpar) cpar.write(file(local_conf, 'w+')) remote.put_file(local_conf, tetcdir + '/tempest.conf') @@ -177,7 +176,6 @@ def task(ctx, config): ceph: conf: client: - rgw keystone url: http://localhost:35357 rgw keystone admin token: ADMIN rgw keystone accepted roles: admin,Member rgw keystone implicit tenants: true @@ -195,17 +193,20 @@ def task(ctx, config): # accompanying stuff, the whole Swift API must be put in root # of the whole URL hierarchy (read: frontend_prefix == /swift). frontend_prefix: /swift + client.0: + use-keystone-role: client.0 - tempest: client.0: force-branch: master + use-keystone-role: client.0 auth: admin_username: admin admin_project_name: admin admin_password: ADMIN admin_domain_name: Default identity: - uri: http://127.0.0.1:5000/v2.0/ - uri_v3: http://127.0.0.1:5000/v3/ + uri: http://{keystone_public_host}:{keystone_public_port}/v2.0/ + uri_v3: http://{keystone_public_host}:{keystone_public_port}/v3/ admin_role: admin object-storage: reseller_admin_role: admin @@ -228,6 +229,8 @@ def task(ctx, config): if not ctx.tox: raise ConfigError('tempest must run after the tox task') + if not ctx.keystone: + raise ConfigError('tempest must run after the keystone task') all_clients = ['client.{id}'.format(id=id_) for id_ in teuthology.all_roles_of_type(ctx.cluster, 'client')]