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:
parent
a47c3edc2d
commit
f83f35c9e2
|
@ -33,3 +33,5 @@
|
|||
password: 'test_password'
|
||||
types:
|
||||
- 'admin'
|
||||
resources:
|
||||
network: 'public'
|
||||
|
|
|
@ -69,9 +69,12 @@ class ListServerFiltersTestJSON(base.BaseV2ComputeTest):
|
|||
|
||||
network = cls.get_tenant_network()
|
||||
if network:
|
||||
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)
|
||||
cls.s1_name = data_utils.rand_name(cls.__name__ + '-instance')
|
||||
cls.s1 = cls.create_test_server(name=cls.s1_name,
|
||||
|
|
|
@ -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"\
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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):
|
||||
|
||||
|
|
Loading…
Reference in New Issue