Add network support to the accounts providers

This commits adds support for specifying the network to use with a
user/tenant into the accounts.yaml file. You can only specify a single
network which will be the network used for all that requires a
pre-existing network. This also means regardless of which cred provider
is configured the fixed_network can assume a TestResource object will
be returned from a get_creds call. As part of this change a common
method to return the full network dict from a just a network name is
abstracted out into tempest.common.fixed_network module since this
same method is needed to have the accounts file provide a network by
name.

Partially-implements: bp test-accounts-continued
Change-Id: I6f5ac1239d18f2935847b385a08de608f40fdda5
This commit is contained in:
Matthew Treinish 2015-04-10 11:59:11 -04:00
parent a47c3edc2d
commit f83f35c9e2
No known key found for this signature in database
GPG Key ID: FD12A0F214C9E177
5 changed files with 137 additions and 71 deletions

View File

@ -33,3 +33,5 @@
password: 'test_password'
types:
- 'admin'
resources:
network: 'public'

View File

@ -69,7 +69,10 @@ class ListServerFiltersTestJSON(base.BaseV2ComputeTest):
network = cls.get_tenant_network()
if network:
cls.fixed_network_name = network['name']
if network.get('name'):
cls.fixed_network_name = network['name']
else:
cls.fixed_network_name = None
else:
cls.fixed_network_name = None
network_kwargs = fixed_network.set_networks_kwarg(network)

View File

@ -19,7 +19,9 @@ from oslo_concurrency import lockutils
from oslo_log import log as logging
import yaml
from tempest import clients
from tempest.common import cred_provider
from tempest.common import fixed_network
from tempest import config
from tempest import exceptions
@ -60,15 +62,18 @@ class Accounts(cred_provider.CredentialProvider):
@classmethod
def get_hash_dict(cls, accounts):
hash_dict = {'roles': {}, 'creds': {}}
hash_dict = {'roles': {}, 'creds': {}, 'networks': {}}
# Loop over the accounts read from the yaml file
for account in accounts:
roles = []
types = []
resources = []
if 'roles' in account:
roles = account.pop('roles')
if 'types' in account:
types = account.pop('types')
if 'resources' in account:
resources = account.pop('resources')
temp_hash = hashlib.md5()
temp_hash.update(str(account))
temp_hash_key = temp_hash.hexdigest()
@ -91,6 +96,13 @@ class Accounts(cred_provider.CredentialProvider):
CONF.object_storage.reseller_admin_role,
temp_hash_key,
hash_dict)
# Populate the network subdict
for resource in resources:
if resource == 'network':
hash_dict['networks'][temp_hash_key] = resources[resource]
else:
LOG.warning('Unkown resource type %s, ignoring this field'
% resource)
return hash_dict
def is_multi_user(self):
@ -174,7 +186,7 @@ class Accounts(cred_provider.CredentialProvider):
"Account file %s doesn't exist" % CONF.auth.test_accounts_file)
useable_hashes = self._get_match_hash_list(roles)
free_hash = self._get_free_hash(useable_hashes)
return self.hash_dict['creds'][free_hash]
return self._wrap_creds_with_network(free_hash)
@lockutils.synchronized('test_accounts_io', external=True)
def remove_hash(self, hash_string):
@ -209,20 +221,16 @@ class Accounts(cred_provider.CredentialProvider):
def get_primary_creds(self):
if self.isolated_creds.get('primary'):
return self.isolated_creds.get('primary')
creds = self._get_creds()
primary_credential = cred_provider.get_credentials(
identity_version=self.identity_version, **creds)
self.isolated_creds['primary'] = primary_credential
return primary_credential
net_creds = self._get_creds()
self.isolated_creds['primary'] = net_creds
return net_creds
def get_alt_creds(self):
if self.isolated_creds.get('alt'):
return self.isolated_creds.get('alt')
creds = self._get_creds()
alt_credential = cred_provider.get_credentials(
identity_version=self.identity_version, **creds)
self.isolated_creds['alt'] = alt_credential
return alt_credential
net_creds = self._get_creds()
self.isolated_creds['alt'] = net_creds
return net_creds
def get_creds_by_roles(self, roles, force_new=False):
roles = list(set(roles))
@ -235,11 +243,9 @@ class Accounts(cred_provider.CredentialProvider):
elif exist_creds and force_new:
new_index = str(roles) + '-' + str(len(self.isolated_creds))
self.isolated_creds[new_index] = exist_creds
creds = self._get_creds(roles=roles)
role_credential = cred_provider.get_credentials(
identity_version=self.identity_version, **creds)
self.isolated_creds[str(roles)] = role_credential
return role_credential
net_creds = self._get_creds(roles=roles)
self.isolated_creds[str(roles)] = net_creds
return net_creds
def clear_isolated_creds(self):
for creds in self.isolated_creds.values():
@ -259,6 +265,19 @@ class Accounts(cred_provider.CredentialProvider):
def admin_available(self):
return self.is_role_available(CONF.identity.admin_role)
def _wrap_creds_with_network(self, hash):
creds_dict = self.hash_dict['creds'][hash]
credential = cred_provider.get_credentials(
identity_version=self.identity_version, **creds_dict)
net_creds = cred_provider.TestResources(credential)
net_clients = clients.Manager(credentials=credential)
compute_network_client = net_clients.networks_client
net_name = self.hash_dict['networks'].get(hash, None)
network = fixed_network.get_network_from_name(
net_name, compute_network_client)
net_creds.set_resources(network=network)
return net_creds
class NotLockingAccounts(Accounts):
"""Credentials provider which always returns the first and second
@ -289,8 +308,9 @@ class NotLockingAccounts(Accounts):
return self.isolated_creds.get('primary')
primary_credential = cred_provider.get_configured_credentials(
credential_type='user', identity_version=self.identity_version)
self.isolated_creds['primary'] = primary_credential
return primary_credential
self.isolated_creds['primary'] = cred_provider.TestResources(
primary_credential)
return self.isolated_creds['primary']
def get_alt_creds(self):
if self.isolated_creds.get('alt'):
@ -298,8 +318,9 @@ class NotLockingAccounts(Accounts):
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
self.isolated_creds['alt'] = cred_provider.TestResources(
alt_credential)
return self.isolated_creds['alt']
def clear_isolated_creds(self):
self.isolated_creds = {}
@ -307,8 +328,8 @@ class NotLockingAccounts(Accounts):
def get_admin_creds(self):
creds = cred_provider.get_configured_credentials(
"identity_admin", fill_in=False)
self.isolated_creds['admin'] = creds
return creds
self.isolated_creds['admin'] = cred_provider.TestResources(creds)
return self.isolated_creds['admin']
def get_creds_by_roles(self, roles, force_new=False):
msg = "Credentials being specified through the config file can not be"\

View File

@ -16,15 +16,67 @@ from oslo_log import log as logging
from tempest_lib.common.utils import misc as misc_utils
from tempest_lib import exceptions as lib_exc
from tempest.common import isolated_creds
from tempest import config
from tempest import exceptions
CONF = config.CONF
LOG = logging.getLogger(__name__)
def get_network_from_name(name, compute_networks_client):
"""Get a full network dict from just a network name
:param str name: the name of the network to use
:param NetworksClientJSON compute_networks_client: The network client
object to use for making the network lists api request
:return: The full dictionary for the network in question, unless the
network for the supplied name can not be found. In which case a dict
with just the name will be returned.
:rtype: dict
"""
caller = misc_utils.find_test_caller()
if not name:
network = {'name': name}
else:
try:
resp = compute_networks_client.list_networks(name=name)
if isinstance(resp, list):
networks = resp
elif isinstance(resp, dict):
networks = resp['networks']
else:
raise lib_exc.NotFound()
if len(networks) > 0:
network = networks[0]
else:
msg = "Network with name: %s not found" % name
if caller:
LOG.warn('(%s) %s' % (caller, msg))
else:
LOG.warn(msg)
raise lib_exc.NotFound()
# To be consistent with network isolation, add name is only
# label is available
name = network.get('name', network.get('label'))
if name:
network['name'] = name
else:
raise lib_exc.NotFound()
except lib_exc.NotFound:
# In case of nova network, if the fixed_network_name is not
# owned by the tenant, and the network client is not an admin
# one, list_networks will not find it
msg = ('Unable to find network %s. '
'Starting instance without specifying a network.' %
name)
if caller:
LOG.info('(%s) %s' % (caller, msg))
else:
LOG.info(msg)
network = {'name': name}
return network
def get_tenant_network(creds_provider, compute_networks_client):
"""Get a network usable by the primary tenant
@ -38,15 +90,9 @@ def get_tenant_network(creds_provider, compute_networks_client):
"""
caller = misc_utils.find_test_caller()
fixed_network_name = CONF.compute.fixed_network_name
network = None
# NOTE(andreaf) get_primary_network will always be available once
# bp test-accounts-continued is implemented
if (isinstance(creds_provider, isolated_creds.IsolatedCreds) and
(CONF.service_available.neutron and
not CONF.service_available.ironic)):
# tenant_allow_isolation == True, so network is defined
network = creds_provider.get_primary_creds().network
else:
net_creds = creds_provider.get_primary_creds()
network = getattr(net_creds, 'network', None)
if not network or not network.get('name'):
if fixed_network_name:
msg = ('No valid network provided or created, defaulting to '
'fixed_network_name')
@ -54,41 +100,8 @@ def get_tenant_network(creds_provider, compute_networks_client):
LOG.debug('(%s) %s' % (caller, msg))
else:
LOG.debug(msg)
try:
resp = compute_networks_client.list_networks(
name=fixed_network_name)
if isinstance(resp, list):
networks = resp
elif isinstance(resp, dict):
networks = resp['networks']
else:
raise lib_exc.NotFound()
if len(networks) > 0:
network = networks[0]
else:
msg = "Configured fixed_network_name not found"
if caller:
msg = '(%s) %s' % (caller, msg)
raise exceptions.InvalidConfiguration(msg)
# To be consistent with network isolation, add name is only
# label is available
name = network.get('name', network.get('label'))
if name:
network['name'] = name
else:
raise lib_exc.NotFound()
except lib_exc.NotFound:
# In case of nova network, if the fixed_network_name is not
# owned by the tenant, and the network client is not an admin
# one, list_networks will not find it
msg = ('Unable to find network %s. '
'Starting instance without specifying a network.' %
fixed_network_name)
if caller:
LOG.info('(%s) %s' % (caller, msg))
else:
LOG.info(msg)
network = {'name': fixed_network_name}
network = get_network_from_name(fixed_network_name,
compute_networks_client)
msg = ('Found network %s available for tenant' % network)
if caller:
LOG.info('(%s) %s' % (caller, msg))

View File

@ -23,11 +23,13 @@ from oslotest import mockpatch
from tempest import auth
from tempest.common import accounts
from tempest.common import cred_provider
from tempest import config
from tempest import exceptions
from tempest.services.identity.v2.json import token_client
from tempest.tests import base
from tempest.tests import fake_config
from tempest.tests import fake_http
from tempest.tests import fake_identity
@ -37,6 +39,9 @@ class TestAccount(base.TestCase):
super(TestAccount, self).setUp()
self.useFixture(fake_config.ConfigFixture())
self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
self.fake_http = fake_http.fake_httplib2(return_type=200)
self.stubs.Set(token_client.TokenClientJSON, 'raw_request',
fake_identity._fake_v2_response)
self.useFixture(lockutils_fixtures.ExternalLockFixture())
self.test_accounts = [
{'username': 'test_user1', 'tenant_name': 'test_tenant1',
@ -63,6 +68,11 @@ class TestAccount(base.TestCase):
'password': 'p', 'roles': [cfg.CONF.identity.admin_role]},
{'username': 'test_user12', 'tenant_name': 'test_tenant12',
'password': 'p', 'roles': [cfg.CONF.identity.admin_role]},
{'username': 'test_user13', 'tenant_name': 'test_tenant13',
'password': 'p', 'resources': {'network': 'network-1'}},
{'username': 'test_user14', 'tenant_name': 'test_tenant14',
'password': 'p', 'roles': ['role-7', 'role-11'],
'resources': {'network': 'network-2'}},
]
self.useFixture(mockpatch.Patch(
'tempest.common.accounts.read_accounts_yaml',
@ -271,10 +281,27 @@ class TestAccount(base.TestCase):
calls = get_free_hash_mock.mock.mock_calls
self.assertEqual(len(calls), 1)
args = calls[0][1][0]
self.assertEqual(len(args), 10)
self.assertEqual(len(args), 12)
for i in admin_hashes:
self.assertNotIn(i, args)
def test_networks_returned_with_creds(self):
self.useFixture(mockpatch.Patch(
'tempest.common.accounts.read_accounts_yaml',
return_value=self.test_accounts))
test_accounts_class = accounts.Accounts('v2', 'test_name')
with mock.patch('tempest.services.compute.json.networks_client.'
'NetworksClientJSON.list_networks',
return_value=[{'name': 'network-2', 'id': 'fake-id'}]):
creds = test_accounts_class.get_creds_by_roles(['role-7'])
self.assertTrue(isinstance(creds, cred_provider.TestResources))
network = creds.network
self.assertIsNotNone(network)
self.assertIn('name', network)
self.assertIn('id', network)
self.assertEqual('fake-id', network['id'])
self.assertEqual('network-2', network['name'])
class TestNotLockingAccount(base.TestCase):