Merge "Seek network resources from tempest"
This commit is contained in:
commit
e52b78d3d8
@ -14,21 +14,15 @@
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import inspect
|
||||
import ipaddress
|
||||
import re
|
||||
import traceback
|
||||
|
||||
from oslo_concurrency import lockutils
|
||||
from oslo_log import log
|
||||
import six
|
||||
from tempest.common import credentials_factory as common_creds
|
||||
|
||||
from tempest import config
|
||||
from tempest.lib.common import cred_client
|
||||
from tempest.lib.common import dynamic_creds
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib.common.utils import test_utils
|
||||
from tempest.lib import exceptions
|
||||
from tempest import test
|
||||
|
||||
@ -99,20 +93,6 @@ class handle_cleanup_exceptions(object):
|
||||
return True # Suppress error if any
|
||||
|
||||
|
||||
def network_synchronized(f):
|
||||
|
||||
def wrapped_func(self, *args, **kwargs):
|
||||
|
||||
# Use lock assuming reusage of common network.
|
||||
@lockutils.synchronized("manila_network_lock", external=True)
|
||||
def source_func(self, *args, **kwargs):
|
||||
return f(self, *args, **kwargs)
|
||||
|
||||
return source_func(self, *args, **kwargs)
|
||||
|
||||
return wrapped_func
|
||||
|
||||
|
||||
skip_if_microversion_not_supported = utils.skip_if_microversion_not_supported
|
||||
skip_if_microversion_lt = utils.skip_if_microversion_lt
|
||||
|
||||
@ -146,36 +126,6 @@ class BaseSharesTest(test.BaseTestCase):
|
||||
"Microversion must be greater than or equal to '%s'." %
|
||||
microversion)
|
||||
|
||||
@classmethod
|
||||
def _get_dynamic_creds(cls, name, network_resources=None):
|
||||
identity_version = CONF.identity.auth_version
|
||||
if identity_version == 'v3':
|
||||
identity_uri = CONF.identity.uri_v3
|
||||
identity_admin_endpoint_type = CONF.identity.v3_endpoint_type
|
||||
elif identity_version == 'v2':
|
||||
identity_uri = CONF.identity.uri
|
||||
identity_admin_endpoint_type = CONF.identity.v2_admin_endpoint_type
|
||||
|
||||
return dynamic_creds.DynamicCredentialProvider(
|
||||
identity_version=identity_version,
|
||||
name=name,
|
||||
network_resources=network_resources,
|
||||
credentials_domain=CONF.auth.default_credentials_domain_name,
|
||||
admin_role=CONF.identity.admin_role,
|
||||
admin_creds=common_creds.get_configured_admin_credentials(),
|
||||
identity_admin_domain_scope=CONF.identity.admin_domain_scope,
|
||||
identity_admin_role=CONF.identity.admin_role,
|
||||
extra_roles=None,
|
||||
neutron_available=CONF.service_available.neutron,
|
||||
create_networks=(
|
||||
CONF.share.create_networks_when_multitenancy_enabled),
|
||||
project_network_cidr=CONF.network.project_network_cidr,
|
||||
project_network_mask_bits=CONF.network.project_network_mask_bits,
|
||||
public_network_id=CONF.network.public_network_id,
|
||||
resource_prefix='tempest',
|
||||
identity_admin_endpoint_type=identity_admin_endpoint_type,
|
||||
identity_uri=identity_uri)
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(BaseSharesTest, cls).skip_checks()
|
||||
@ -191,6 +141,24 @@ class BaseSharesTest(test.BaseTestCase):
|
||||
msg = "Missing API credentials in configuration."
|
||||
raise cls.skipException(msg)
|
||||
|
||||
@classmethod
|
||||
def setup_credentials(cls):
|
||||
# This call is used to tell the credential allocator to create
|
||||
# network resources for this test case. NOTE: it must go before the
|
||||
# super call, to override decisions in the base classes.
|
||||
network_resources = {}
|
||||
if (CONF.share.multitenancy_enabled and
|
||||
CONF.share.create_networks_when_multitenancy_enabled):
|
||||
# We're testing a DHSS=True driver, and manila is configured with
|
||||
# NeutronNetworkPlugin (or a derivative) that supports creating
|
||||
# share networks with project neutron networks, so lets ask for
|
||||
# neutron network resources to be created with test credentials
|
||||
network_resources.update({'network': True,
|
||||
'subnet': True,
|
||||
'router': True})
|
||||
cls.set_network_resources(**network_resources)
|
||||
super(BaseSharesTest, cls).setup_credentials()
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(BaseSharesTest, cls).setup_clients()
|
||||
@ -198,46 +166,26 @@ class BaseSharesTest(test.BaseTestCase):
|
||||
# Initialise share clients for test credentials
|
||||
cls.shares_client = os.share_v1.SharesClient()
|
||||
cls.shares_v2_client = os.share_v2.SharesV2Client()
|
||||
cls.admin_nc = cls.admin_snc = cls.admin_rc = cls.admin_net_cred = None
|
||||
# Initialise network clients for test credentials
|
||||
cls.networks_client = None
|
||||
cls.subnets_client = None
|
||||
if CONF.service_available.neutron:
|
||||
cls.networks_client = os.network.NetworksClient()
|
||||
cls.subnets_client = os.network.SubnetsClient()
|
||||
if CONF.share.multitenancy_enabled and (
|
||||
CONF.auth.use_dynamic_credentials):
|
||||
# Get admin credentials so we can create neutron networks
|
||||
# dynamically if/when needed
|
||||
(cls.admin_nc, cls.admin_snc,
|
||||
cls.admin_rc, cls.admin_net_cred) = (
|
||||
cls.get_network_clients_with_isolated_creds())
|
||||
else:
|
||||
cls.networks_client = None
|
||||
cls.subnets_client = None
|
||||
|
||||
cls.project_network_cidr = CONF.network.project_network_cidr
|
||||
cls.public_network_id = CONF.network.public_network_id
|
||||
|
||||
if CONF.identity.auth_version == 'v3':
|
||||
project_id = os.auth_provider.auth_data[1]['project']['id']
|
||||
else:
|
||||
project_id = os.auth_provider.auth_data[1]['token']['tenant']['id']
|
||||
cls.tenant_id = project_id
|
||||
cls.user_id = os.auth_provider.auth_data[1]['user']['id']
|
||||
|
||||
# If DHSS=True, create a share network and set it in the client
|
||||
# for easy access.
|
||||
if CONF.share.multitenancy_enabled:
|
||||
if (not CONF.service_available.neutron and
|
||||
CONF.share.create_networks_when_multitenancy_enabled):
|
||||
raise cls.skipException("Neutron support is required")
|
||||
raise cls.skipException(
|
||||
"Neutron support is required when "
|
||||
"CONF.share.create_networks_when_multitenancy_enabled "
|
||||
"is set to True")
|
||||
share_network_id = cls.provide_share_network(
|
||||
cls.shares_v2_client, cls.networks_client)
|
||||
cls.shares_client, cls.networks_client)
|
||||
cls.shares_client.share_network_id = share_network_id
|
||||
cls.shares_v2_client.share_network_id = share_network_id
|
||||
resource = {
|
||||
"type": "share_network",
|
||||
"id": share_network_id,
|
||||
"client": cls.shares_v2_client,
|
||||
}
|
||||
cls.class_resources.insert(0, resource)
|
||||
|
||||
def setUp(self):
|
||||
super(BaseSharesTest, self).setUp()
|
||||
@ -247,8 +195,6 @@ class BaseSharesTest(test.BaseTestCase):
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.clear_resources(cls.class_resources)
|
||||
if cls.admin_net_cred:
|
||||
cls.admin_net_cred.clear_creds()
|
||||
super(BaseSharesTest, cls).resource_cleanup()
|
||||
|
||||
@classmethod
|
||||
@ -335,170 +281,73 @@ class BaseSharesTest(test.BaseTestCase):
|
||||
cls.method_resources.insert(0, resource)
|
||||
|
||||
@classmethod
|
||||
@network_synchronized
|
||||
def provide_share_network(cls, shares_client, networks_client,
|
||||
ignore_multitenancy_config=False):
|
||||
"""Used for finding/creating share network for multitenant driver.
|
||||
"""Get or create share network for DHSS=True drivers
|
||||
|
||||
This method creates/gets entity share-network for one tenant. This
|
||||
share-network will be used for creation of service vm.
|
||||
|
||||
:param shares_client: shares client, which requires share-network
|
||||
:param networks_client: network client from same tenant as shares
|
||||
:param ignore_multitenancy_config: provide a share network regardless
|
||||
of 'multitenancy_enabled' configuration value.
|
||||
When testing DHSS=True (multitenancy_enabled) drivers, shares must
|
||||
be requested on share networks.
|
||||
:returns: str -- share network id for shares_client tenant
|
||||
:returns: None -- if single-tenant driver used
|
||||
:returns: None -- if single-tenant driver (DHSS=False) is used
|
||||
"""
|
||||
|
||||
sc = shares_client
|
||||
sn_name = "autogenerated_by_tempest"
|
||||
|
||||
if (not ignore_multitenancy_config and
|
||||
not CONF.share.multitenancy_enabled):
|
||||
# Assumed usage of a single-tenant driver
|
||||
# Assumed usage of a single-tenant driver (DHSS=False)
|
||||
return None
|
||||
else:
|
||||
if sc.share_network_id:
|
||||
# Share-network already exists, use it
|
||||
return sc.share_network_id
|
||||
elif not CONF.share.create_networks_when_multitenancy_enabled:
|
||||
# We need a new share network, but don't need to associate
|
||||
# any neutron networks to it - this configuration is used
|
||||
# when manila is configured with "StandaloneNetworkPlugin"
|
||||
# or "NeutronSingleNetworkPlugin" where all tenants share
|
||||
# a single backend network where shares are exported.
|
||||
sn_desc = "This share-network was created by tempest"
|
||||
sn = cls.create_share_network(cleanup_in_class=True,
|
||||
add_security_services=True,
|
||||
name=sn_name,
|
||||
description=sn_desc)
|
||||
return sn['id']
|
||||
else:
|
||||
net_id = subnet_id = None
|
||||
# Retrieve non-public network list owned by the tenant
|
||||
search_opts = {'tenant_id': sc.tenant_id, 'shared': False}
|
||||
tenant_networks = (
|
||||
networks_client.list_networks(
|
||||
**search_opts).get('networks', [])
|
||||
)
|
||||
tenant_networks_with_subnet = (
|
||||
[n for n in tenant_networks if n['subnets']]
|
||||
)
|
||||
|
||||
if tenant_networks_with_subnet:
|
||||
net_id = tenant_networks_with_subnet[0]['id']
|
||||
subnet_id = tenant_networks_with_subnet[0]['subnets'][0]
|
||||
if shares_client.share_network_id:
|
||||
# Share-network already exists, use it
|
||||
return shares_client.share_network_id
|
||||
|
||||
if net_id is None or subnet_id is None:
|
||||
network, subnet, router = (
|
||||
cls.provide_network_resources_for_tenant_id(
|
||||
sc.tenant_id)
|
||||
)
|
||||
net_id = network['network']['id']
|
||||
subnet_id = subnet['subnet']['id']
|
||||
sn_name = "autogenerated_by_tempest"
|
||||
sn_desc = "This share-network was created by tempest"
|
||||
|
||||
# Create suitable share-network
|
||||
sn_desc = "This share-network was created by tempest"
|
||||
sn = cls.create_share_network(cleanup_in_class=True,
|
||||
add_security_services=True,
|
||||
name=sn_name,
|
||||
description=sn_desc,
|
||||
neutron_net_id=net_id,
|
||||
neutron_subnet_id=subnet_id)
|
||||
if not CONF.share.create_networks_when_multitenancy_enabled:
|
||||
# We need a new share network, but don't need to associate
|
||||
# any neutron networks to it - this configuration is used
|
||||
# when manila is configured with "StandaloneNetworkPlugin"
|
||||
# or "NeutronSingleNetworkPlugin" where all tenants share
|
||||
# a single backend network where shares are exported.
|
||||
sn = cls.create_share_network(cleanup_in_class=True,
|
||||
client=shares_client,
|
||||
add_security_services=True,
|
||||
name=sn_name,
|
||||
description=sn_desc)
|
||||
return sn['id']
|
||||
|
||||
return sn['id']
|
||||
# Retrieve non-public network list owned by the tenant
|
||||
filters = {'project_id': shares_client.tenant_id,
|
||||
'shared': False}
|
||||
tenant_networks = (
|
||||
networks_client.list_networks(**filters).get('networks', [])
|
||||
)
|
||||
tenant_networks_with_subnet = (
|
||||
[n for n in tenant_networks if n['subnets']]
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def provide_network_resources_for_tenant_id(cls, tenant_id):
|
||||
"""Used for creating neutron network resources.
|
||||
if not tenant_networks_with_subnet:
|
||||
# This can only occur if using tempest's pre-provisioned
|
||||
# credentials and not allocating networks to them
|
||||
raise cls.skipException(
|
||||
"Test credentials must provide at least one "
|
||||
"non-shared project network with a valid subnet when "
|
||||
"CONF.share.create_networks_when_multitenancy_enabled is "
|
||||
"set to True.")
|
||||
|
||||
This method creates a suitable network, subnet and router
|
||||
to be used when providing a new share network in the tempest.
|
||||
The tempest conf project_network_cidr is very important
|
||||
in order to create a reachable network. Also, this method will
|
||||
cleanup the neutron resources in the class teardown.
|
||||
net_id = tenant_networks_with_subnet[0]['id']
|
||||
subnet_id = tenant_networks_with_subnet[0]['subnets'][0]
|
||||
|
||||
:param tenant_id: tenant_id to be used for network resources creation
|
||||
:returns network, subnet, router: the neutron resources created
|
||||
"""
|
||||
# Create suitable share-network
|
||||
sn = cls.create_share_network(cleanup_in_class=True,
|
||||
client=shares_client,
|
||||
add_security_services=True,
|
||||
name=sn_name,
|
||||
description=sn_desc,
|
||||
neutron_net_id=net_id,
|
||||
neutron_subnet_id=subnet_id)
|
||||
|
||||
network = cls.admin_nc.create_network(
|
||||
tenant_id=tenant_id,
|
||||
name="tempest-net")
|
||||
cls.addClassResourceCleanup(
|
||||
test_utils.call_and_ignore_notfound_exc,
|
||||
cls.admin_nc.delete_network,
|
||||
network['network']['id'])
|
||||
|
||||
subnet = cls.admin_snc.create_subnet(
|
||||
network_id=network['network']['id'],
|
||||
tenant_id=tenant_id,
|
||||
cidr=str(cls.project_network_cidr),
|
||||
name="tempest-subnet",
|
||||
ip_version=(ipaddress.ip_network(
|
||||
six.text_type(cls.project_network_cidr)).version))
|
||||
cls.addClassResourceCleanup(
|
||||
test_utils.call_and_ignore_notfound_exc,
|
||||
cls.admin_snc.delete_subnet,
|
||||
subnet['subnet']['id'])
|
||||
|
||||
router = None
|
||||
if cls.public_network_id:
|
||||
kwargs = {'name': "tempest-router",
|
||||
'tenant_id': tenant_id,
|
||||
'external_gateway_info': cls.public_network_id}
|
||||
body = cls.routers_client.create_router(**kwargs)
|
||||
router = body['router']
|
||||
|
||||
cls.admin_rc.add_router_interface(
|
||||
router['id'],
|
||||
subnet_id=subnet['subnet']['id'])
|
||||
cls.addClassResourceCleanup(
|
||||
test_utils.call_and_ignore_notfound_exc,
|
||||
cls.admin_rc.delete_router, router)
|
||||
cls.addClassResourceCleanup(
|
||||
test_utils.call_and_ignore_notfound_exc,
|
||||
cls.admin_rc.remove_router_interface,
|
||||
router['id'],
|
||||
subnet_id=subnet['subnet']['id'])
|
||||
|
||||
return network, subnet, router
|
||||
|
||||
@classmethod
|
||||
def get_network_clients_with_isolated_creds(cls,
|
||||
name=None,
|
||||
type_of_creds='admin'):
|
||||
"""Creates isolated creds and provide network clients.
|
||||
|
||||
:param name: name, will be used for naming ic and related stuff
|
||||
:param type_of_creds: defines the type of creds to be created
|
||||
:returns: NetworksClient, SubnetsClient, RoutersClient,
|
||||
Isolated Credentials
|
||||
"""
|
||||
|
||||
if name is None:
|
||||
# Get name of test method
|
||||
name = inspect.stack()[1][3]
|
||||
if len(name) > 32:
|
||||
name = name[0:32]
|
||||
# Choose type of isolated creds
|
||||
ic = cls._get_dynamic_creds(name)
|
||||
if "admin" in type_of_creds:
|
||||
creds = ic.get_admin_creds().credentials
|
||||
elif "alt" in type_of_creds:
|
||||
creds = ic.get_alt_creds().credentials
|
||||
else:
|
||||
creds = ic.get_credentials(type_of_creds).credentials
|
||||
ic.type_of_creds = type_of_creds
|
||||
# create client with isolated creds
|
||||
os = clients.Clients(creds)
|
||||
|
||||
net_client = os.network.NetworksClient()
|
||||
subnet_client = os.network.SubnetsClient()
|
||||
router_client = os.network.RoutersClient()
|
||||
|
||||
return net_client, subnet_client, router_client, ic
|
||||
return sn['id']
|
||||
|
||||
@classmethod
|
||||
def _create_share(cls, share_protocol=None, size=None, name=None,
|
||||
@ -1403,12 +1252,6 @@ class BaseSharesMixedTest(BaseSharesTest):
|
||||
cls.alt_shares_v2_client, cls.os_alt.networks_client)
|
||||
cls.alt_shares_client.share_network_id = alt_share_network_id
|
||||
cls.alt_shares_v2_client.share_network_id = alt_share_network_id
|
||||
resource = {
|
||||
"type": "share_network",
|
||||
"id": alt_share_network_id,
|
||||
"client": cls.alt_shares_v2_client,
|
||||
}
|
||||
cls.class_resources.insert(0, resource)
|
||||
|
||||
@classmethod
|
||||
def create_user_and_get_client(cls, project=None):
|
||||
|
Loading…
x
Reference in New Issue
Block a user