diff --git a/etc/accounts.yaml.sample b/etc/accounts.yaml.sample index 64ff8a76cd..31ceb33259 100644 --- a/etc/accounts.yaml.sample +++ b/etc/accounts.yaml.sample @@ -33,3 +33,5 @@ password: 'test_password' types: - 'admin' + resources: + network: 'public' diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py index f33204d75b..eccd6006ef 100644 --- a/tempest/api/compute/servers/test_list_server_filters.py +++ b/tempest/api/compute/servers/test_list_server_filters.py @@ -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) diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py index 1d5516f27a..acf6d4fa91 100644 --- a/tempest/common/accounts.py +++ b/tempest/common/accounts.py @@ -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"\ diff --git a/tempest/common/fixed_network.py b/tempest/common/fixed_network.py index b2d7c0be91..1557474007 100644 --- a/tempest/common/fixed_network.py +++ b/tempest/common/fixed_network.py @@ -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)) diff --git a/tempest/tests/common/test_accounts.py b/tempest/tests/common/test_accounts.py index 6371e494b3..b176675404 100644 --- a/tempest/tests/common/test_accounts.py +++ b/tempest/tests/common/test_accounts.py @@ -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):