Merge "Only use accounts.yaml with locking provider"

This commit is contained in:
Jenkins
2015-03-30 22:10:40 +00:00
committed by Gerrit Code Review
6 changed files with 41 additions and 114 deletions

View File

@@ -84,13 +84,11 @@ in your cloud you might face unexpected failures.
To enable and use locking test accounts you need do a few things:
#. Enable the locking test account provider with the
locking_credentials_provider option in the auth section
#. Create a accounts.yaml file which contains the set of pre-existing
credentials to use for testing. To make sure you don't have a credentials
starvation issue when running in parallel make sure you have at least 2
times the number of parallel workers you are using to execute tempest
available in the file.
times the number of worker processes you are using to execute tempest
available in the file. (if running serially the worker count is 1)
You can check the sample file packaged in tempest for the yaml format
#. Provide tempest with the location of you accounts.yaml file with the
@@ -125,15 +123,3 @@ The only restriction with using the traditional config options for credentials
is that if a test requires specific roles on accounts these tests can not be
run. This is because the config options do not give sufficient flexibility to
describe the roles assigned to a user for running the tests.
You also can use the accounts.yaml file to specify the credentials used for
testing. This will just allocate them serially so you only need to provide
a pair of credentials. Do note that all the restrictions associated with
locking test accounts applies to using the accounts.yaml file this way too,
except since you can't run in parallel only 2 of each type of credential is
required to run. However, the limitation on tests which require specific roles
does not apply here.
The procedure for doing this is very similar to with the locking accounts
provider just don't set the locking_credentials_provider to true and you
only should need a single pair of credentials.

View File

@@ -94,8 +94,12 @@
#
# Path to the yaml file that contains the list of credentials to use
# for running tests (string value)
#test_accounts_file = etc/accounts.yaml
# for running tests. If used when running in parallel you have to make
# sure sufficient credentials are provided in the accounts file. For
# example if no tests with roles are being run it requires at least `2
# * CONC` distinct accounts configured in the `test_accounts_file`,
# with CONC == the number of concurrent test processes. (string value)
#test_accounts_file = <None>
# Allows test cases to create/destroy tenants and users. This option
# requires that OpenStack Identity API admin credentials are known. If
@@ -105,14 +109,6 @@
# Deprecated group/name - [orchestration]/allow_tenant_isolation
#allow_tenant_isolation = true
# If set to True it enables the Accounts provider, which locks
# credentials to allow for parallel execution with pre-provisioned
# accounts. It can only be used to run tests that ensure credentials
# cleanup happens. It requires at least `2 * CONC` distinct accounts
# configured in `test_accounts_file`, with CONC == the number of
# concurrent test processes. (boolean value)
#locking_credentials_provider = false
# Roles to assign to all users created by tempest (list value)
#tempest_roles =

View File

@@ -261,18 +261,14 @@ class NotLockingAccounts(Accounts):
def _unique_creds(self, cred_arg=None):
"""Verify that the configured credentials are valid and distinct """
if self.use_default_creds:
try:
user = self.get_primary_creds()
alt_user = self.get_alt_creds()
return getattr(user, cred_arg) != getattr(alt_user, cred_arg)
except exceptions.InvalidCredentials as ic:
msg = "At least one of the configured credentials is " \
"not valid: %s" % ic.message
raise exceptions.InvalidConfiguration(msg)
else:
# TODO(andreaf) Add a uniqueness check here
return len(self.hash_dict['creds']) > 1
try:
user = self.get_primary_creds()
alt_user = self.get_alt_creds()
return getattr(user, cred_arg) != getattr(alt_user, cred_arg)
except exceptions.InvalidCredentials as ic:
msg = "At least one of the configured credentials is " \
"not valid: %s" % ic.message
raise exceptions.InvalidConfiguration(msg)
def is_multi_user(self):
return self._unique_creds('username')
@@ -280,42 +276,20 @@ class NotLockingAccounts(Accounts):
def is_multi_tenant(self):
return self._unique_creds('tenant_id')
def get_creds(self, id, roles=None):
try:
hashes = self._get_match_hash_list(roles)
# No need to sort the dict as within the same python process
# the HASH seed won't change, so subsequent calls to keys()
# will return the same result
_hash = hashes[id]
except IndexError:
msg = 'Insufficient number of users provided'
raise exceptions.InvalidConfiguration(msg)
return self.hash_dict['creds'][_hash]
def get_primary_creds(self):
if self.isolated_creds.get('primary'):
return self.isolated_creds.get('primary')
if not self.use_default_creds:
creds = self.get_creds(0)
primary_credential = cred_provider.get_credentials(
identity_version=self.identity_version, **creds)
else:
primary_credential = cred_provider.get_configured_credentials(
credential_type='user', identity_version=self.identity_version)
primary_credential = cred_provider.get_configured_credentials(
credential_type='user', identity_version=self.identity_version)
self.isolated_creds['primary'] = primary_credential
return primary_credential
def get_alt_creds(self):
if self.isolated_creds.get('alt'):
return self.isolated_creds.get('alt')
if not self.use_default_creds:
creds = self.get_creds(1)
alt_credential = cred_provider.get_credentials(
identity_version=self.identity_version, **creds)
else:
alt_credential = cred_provider.get_configured_credentials(
credential_type='alt_user',
identity_version=self.identity_version)
alt_credential = cred_provider.get_configured_credentials(
credential_type='alt_user',
identity_version=self.identity_version)
self.isolated_creds['alt'] = alt_credential
return alt_credential
@@ -323,35 +297,14 @@ class NotLockingAccounts(Accounts):
self.isolated_creds = {}
def get_admin_creds(self):
if not self.use_default_creds:
return self.get_creds_by_roles([CONF.identity.admin_role])
else:
creds = cred_provider.get_configured_credentials(
"identity_admin", fill_in=False)
self.isolated_creds['admin'] = creds
return creds
creds = cred_provider.get_configured_credentials(
"identity_admin", fill_in=False)
self.isolated_creds['admin'] = creds
return creds
def get_creds_by_roles(self, roles, force_new=False):
roles = list(set(roles))
exist_creds = self.isolated_creds.get(str(roles), None)
index = 0
if exist_creds and not force_new:
return exist_creds
elif exist_creds and force_new:
new_index = str(roles) + '-' + str(len(self.isolated_creds))
self.isolated_creds[new_index] = exist_creds
# Figure out how many existing creds for this roles set are present
# use this as the index the returning hash list to ensure separate
# creds are returned with force_new being True
for creds_names in self.isolated_creds:
if str(roles) in creds_names:
index = index + 1
if not self.use_default_creds:
creds = self.get_creds(index, roles=roles)
role_credential = cred_provider.get_credentials(**creds)
self.isolated_creds[str(roles)] = role_credential
else:
msg = "Default credentials can not be used with specifying "\
"credentials by roles"
raise exceptions.InvalidConfiguration(msg)
return role_credential
msg = "Credentials being specified through the config file can not be"\
" used with tests that specify using credentials by roles. "\
"Either exclude/skip the tests doing this or use either an "\
"test_accounts_file or tenant isolation."
raise exceptions.InvalidConfiguration(msg)

View File

@@ -38,7 +38,7 @@ def get_isolated_credentials(name, network_resources=None,
network_resources=network_resources,
identity_version=identity_version)
else:
if CONF.auth.locking_credentials_provider:
if os.path.isfile(CONF.auth.test_accounts_file):
# Most params are not relevant for pre-created accounts
return accounts.Accounts(name=name,
identity_version=identity_version)

View File

@@ -35,9 +35,14 @@ auth_group = cfg.OptGroup(name='auth',
AuthGroup = [
cfg.StrOpt('test_accounts_file',
default='etc/accounts.yaml',
help="Path to the yaml file that contains the list of "
"credentials to use for running tests"),
"credentials to use for running tests. If used when "
"running in parallel you have to make sure sufficient "
"credentials are provided in the accounts file. For "
"example if no tests with roles are being run it requires "
"at least `2 * CONC` distinct accounts configured in "
" the `test_accounts_file`, with CONC == the "
"number of concurrent test processes."),
cfg.BoolOpt('allow_tenant_isolation',
default=True,
help="Allows test cases to create/destroy tenants and "
@@ -49,15 +54,6 @@ AuthGroup = [
group='compute'),
cfg.DeprecatedOpt('allow_tenant_isolation',
group='orchestration')]),
cfg.BoolOpt('locking_credentials_provider',
default=False,
help="If set to True it enables the Accounts provider, "
"which locks credentials to allow for parallel execution "
"with pre-provisioned accounts. It can only be used to "
"run tests that ensure credentials cleanup happens. "
"It requires at least `2 * CONC` distinct accounts "
"configured in `test_accounts_file`, with CONC == the "
"number of concurrent test processes."),
cfg.ListOpt('tempest_roles',
help="Roles to assign to all users created by tempest",
default=[]),

View File

@@ -297,12 +297,8 @@ class TestNotLockingAccount(base.TestCase):
cfg.CONF.set_default('test_accounts_file', '', group='auth')
self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
def test_get_creds(self):
def test_get_creds_roles_nonlocking_invalid(self):
test_accounts_class = accounts.NotLockingAccounts('v2', 'test_name')
for i in xrange(len(self.test_accounts)):
creds = test_accounts_class.get_creds(i)
msg = "Empty credentials returned for ID %s" % str(i)
self.assertIsNotNone(creds, msg)
self.assertRaises(exceptions.InvalidConfiguration,
test_accounts_class.get_creds,
id=len(self.test_accounts))
test_accounts_class.get_creds_by_roles,
['fake_role'])