1 setUpClass()流程
setUpClass()要完成用例跳过、凭证建立的任务,这两个任务分别调用skip_check()和setup_credential()来完成。setup_client()和resource_setup()一般由测试用例脚本覆盖基类函数完成,基类中这两个函数均为空。
2 skip_checks()
@classmethods
def skip_checks(cls):
cls.__skip_checks_called = True
identity_version = cls.get_identity_version()
# setting force_tenant_isolation to True also needs admin credentials.
if ('admin' in cls.credentials or
getattr(cls, 'force_tenant_isolation', False)):
if not credentials.is_admin_available(
identity_version=identity_version):
raise cls.skipException(
"Missing Identity Admin API credentials in configuration.")
if 'alt' in cls.credentials and not credentials.is_alt_available(
identity_version=identity_version):
msg = "Missing a 2nd set of API credentials in configuration."
raise cls.skipException(msg)
if hasattr(cls, 'identity_version'):
if cls.identity_version == 'v2':
if not CONF.identity_feature_enabled.api_v2:
raise cls.skipException("Identity api v2 is not enabled")
elif cls.identity_version == 'v3':
if not CONF.identity_feature_enabled.api_v3:
raise cls.skipException("Identity api v3 is not enabled")
skip_checks()中主要检查有无admin权限,以及认证服务的版本。
测试用例类覆盖该函数,抛出skipException异常以达到跳过用例的目的,例如:
@classmethod
def skip_checks(cls):
super(VolumesBackupsTest, cls).skip_checks()
if not CONF.volume_feature_enabled.backup:
raise cls.skipException("Cinder backup feature disabled")
一般skip_checks()只能根据配置文件跳过用例。如果被测环境资源不足,skip_checks()函数并不能检查到并跳过用例,因为此时客户端还未加载,不具备与被测平台通信的条件。
3 setup_credentials()
@classmethod
def setup_credentials(cls):
cls.__setup_credentials_called = True
for credentials_type in cls.credentials:
# This may raise an exception in case credentials are not available
# In that case we want to let the exception through and the test
# fail accordingly
if isinstance(credentials_type, six.string_types):
manager = cls.get_client_manager(
credential_type=credentials_type)
setattr(cls, 'os_%s' % credentials_type, manager)
# NOTE(jordanP): Tempest should use os_primary, os_admin
# and os_alt throughout its code base but we keep the aliases
# around for a while for Tempest plugins. Aliases should be
# removed eventually.
# Setup some common aliases
if credentials_type == 'primary':
cls.os = debtcollector.moves.moved_read_only_property(
'os', 'os_primary', version='Pike',
removal_version='Queens')
cls.manager =\
debtcollector.moves.moved_read_only_property(
'manager', 'os_primary', version='Pike',
removal_version='Queens')
if credentials_type == 'admin':
cls.os_adm = debtcollector.moves.moved_read_only_property(
'os_adm', 'os_admin', version='Pike',
removal_version='Queens')
cls.admin_manager =\
debtcollector.moves.moved_read_only_property(
'admin_manager', 'os_admin', version='Pike',
removal_version='Queens')
if credentials_type == 'alt':
cls.alt_manager =\
debtcollector.moves.moved_read_only_property(
'alt_manager', 'os_alt', version='Pike',
removal_version='Queens')
elif isinstance(credentials_type, list):
manager = cls.get_client_manager(roles=credentials_type[1:],
force_new=True)
setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
setup_credentials()主要是获取对应凭证下的manager,Tempest的客户端在manager下。规定测试用例使用何种凭证可通过覆盖基类中的cls.credentials完成,如:
credentials = ['primary', 'admin']
指定了测试用例使用普通和admin的凭证信息。
setup_credentials()调用cls.get_client_manager获取manager,过程中涉及两部分:
@classmethod
def get_client_manager(cls, credential_type=None, roles=None,
force_new=None):
if all([roles, credential_type]):
msg = "Cannot get credentials by type and roles at the same time"
raise ValueError(msg)
if not any([roles, credential_type]):
credential_type = 'primary'
cred_provider = cls._get_credentials_provider()
if roles:
for role in roles:
if not cred_provider.is_role_available(role):
skip_msg = (
"%s skipped because the configured credential provider"
" is not able to provide credentials with the %s role "
"assigned." % (cls.__name__, role))
raise cls.skipException(skip_msg)
params = dict(roles=roles)
if force_new is not None:
params.update(force_new=force_new)
creds = cred_provider.get_creds_by_roles(**params)
else:
credentials_method = 'get_%s_creds' % credential_type
if hasattr(cred_provider, credentials_method):
creds = getattr(cred_provider, credentials_method)()
else:
raise lib_exc.InvalidCredentials(
"Invalid credentials type %s" % credential_type)
manager = cls.client_manager(credentials=creds.credentials)
# NOTE(andreaf) Ensure credentials have user and project id fields.
# It may not be the case when using pre-provisioned credentials.
manager.auth_provider.set_auth()
return manager
该过程主要可分为获取cred_provider和初始化manager。
3.1 cred_provider
cred_provider分为dynamic和provision两种,分别对应Tempest笔记003中的两种动态凭证与静态凭证。
def get_credentials_provider(name, network_resources=None,
force_tenant_isolation=False,
identity_version=None):
# If a test requires a new account to work, it can have it via forcing
# dynamic credentials. A new account will be produced only for that test.
# In case admin credentials are not available for the account creation,
# the test should be skipped else it would fail.
identity_version = identity_version or CONF.identity.auth_version
if CONF.auth.use_dynamic_credentials or force_tenant_isolation:
return dynamic_creds.DynamicCredentialProvider(
name=name,
network_resources=network_resources,
**get_dynamic_provider_params(identity_version))
else:
if CONF.auth.test_accounts_file:
# Most params are not relevant for pre-created accounts
return preprov_creds.PreProvisionedCredentialProvider(
name=name,
**get_preprov_provider_params(identity_version))
else:
raise exceptions.InvalidConfiguration(
'A valid credential provider is needed')
根据配置文件中的选项,这里实例化动态或静态凭证。以动态凭证为例,所涉及到的参数有:
- name:credential_provider创建租户和用户用的名称。
- network_resources:创建租户和用户后,是否选择创建网络资源。
这里面的网络资源包含网络、子网、路由、DHCP,如全选则会创建一整套虚拟私有云(Virtual Private Cloud, VPC),路由的网关会根据配置连接到外网。
实例化过程大多是属性的赋值,credentia_provider中的get_%s_creds调用get_credentials完成租户、用户及网络资源的创建。
def get_credentials(self, credential_type):
if self._creds.get(str(credential_type)):
credentials = self._creds[str(credential_type)]
else:
if credential_type in ['primary', 'alt', 'admin']:
is_admin = (credential_type == 'admin')
credentials = self._create_creds(admin=is_admin)
else:
credentials = self._create_creds(roles=credential_type)
self._creds[str(credential_type)] = credentials
# Maintained until tests are ported
LOG.info("Acquired dynamic creds:\n"
" credentials: %s", credentials)
if (self.neutron_available and self.create_networks):
network, subnet, router = self._create_network_resources(
credentials.tenant_id)
credentials.set_resources(network=network, subnet=subnet,
router=router)
LOG.info("Created isolated network resources for:\n"
" credentials: %s", credentials)
return credentials
self._create_creds创建租户和用户,并赋以相应的权限。
self._create_network_resources创建网络、子网、路由。
以上操作均使用配置文件中的admin权限。
3.2 manager
测试用例类中的manager是Manager类的实例,继承了ServiceClients类。实例化的过程中,二者的构造函数都会被调用。在构造函数中,manager根据固定的路径导入路径下所有客户端,并初始化其中的参数。