Merge "Log ip Information on ssh failures in the minimum scenario"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 1d368af..a2d3877 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -553,6 +553,9 @@
# The mask bits for tenant ipv4 subnets (integer value)
#tenant_network_mask_bits=28
+# Allow the execution of IPv6 tests (boolean value)
+#ipv6_enabled=true
+
# The cidr block to allocate tenant ipv6 subnets from (string
# value)
#tenant_network_v6_cidr=2003::/64
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 9029b1f..aba2c8e 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -467,6 +467,14 @@
_tenant_network_cidr = CONF.network.tenant_network_v6_cidr
_tenant_network_mask_bits = CONF.network.tenant_network_v6_mask_bits
+ @classmethod
+ def setUpClass(cls):
+ super(NetworksIpV6TestJSON, cls).setUpClass()
+ if not CONF.network.ipv6_enabled:
+ cls.tearDownClass()
+ skip_msg = "IPv6 Tests are disabled."
+ raise cls.skipException(skip_msg)
+
class NetworksIpV6TestXML(NetworksIpV6TestJSON):
_interface = 'xml'
diff --git a/tempest/auth.py b/tempest/auth.py
index 582cfdd..e1ba13b 100644
--- a/tempest/auth.py
+++ b/tempest/auth.py
@@ -177,7 +177,7 @@
base_url = self.base_url(filters=filters, auth_data=auth_data)
# build authenticated request
# returns new request, it does not touch the original values
- _headers = copy.deepcopy(headers)
+ _headers = copy.deepcopy(headers) if headers is not None else {}
_headers['X-Auth-Token'] = token
if url is None or url == "":
_url = base_url
@@ -371,7 +371,7 @@
ep['region'] == region]
if len(filtered_catalog) == 0:
# No matching region, take the first endpoint
- filtered_catalog = [filtered_catalog[0]]
+ filtered_catalog = [service_catalog[0]]
# There should be only one match. If not take the first.
_base_url = filtered_catalog[0].get('url', None)
if _base_url is None:
diff --git a/tempest/clients.py b/tempest/clients.py
index 3db05e5..8db399a 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -13,10 +13,20 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest import auth
+# Default client libs
+import cinderclient.client
+import glanceclient
+import heatclient.client
+import keystoneclient.exceptions
+import keystoneclient.v2_0.client
+import neutronclient.v2_0.client
+import novaclient.client
+import swiftclient
+
from tempest.common.rest_client import NegativeRestClient
from tempest import config
from tempest import exceptions
+from tempest import manager
from tempest.openstack.common import log as logging
from tempest.services.baremetal.v1.client_json import BaremetalClientJSON
from tempest.services import botoclients
@@ -169,10 +179,10 @@
LOG = logging.getLogger(__name__)
-class Manager(object):
+class Manager(manager.Manager):
"""
- Top level manager for OpenStack Compute clients
+ Top level manager for OpenStack tempest clients
"""
def __init__(self, username=None, password=None, tenant_name=None,
@@ -187,153 +197,145 @@
:param tenant_name: Override of the tenant name
"""
self.interface = interface
- self.auth_version = CONF.identity.auth_version
- # FIXME(andreaf) Change Manager __init__ to accept a credentials dict
- if username is None or password is None:
- # Tenant None is a valid use case
- self.credentials = self.get_default_credentials()
- else:
- self.credentials = dict(username=username, password=password,
- tenant_name=tenant_name)
- if self.auth_version == 'v3':
- self.credentials['domain_name'] = 'Default'
- # Setup an auth provider
- auth_provider = self.get_auth_provider(self.credentials)
+ self.client_type = 'tempest'
+ # super cares for credentials validation
+ super(Manager, self).__init__(
+ username=username, password=password, tenant_name=tenant_name)
if self.interface == 'xml':
self.certificates_client = CertificatesClientXML(
- auth_provider)
- self.servers_client = ServersClientXML(auth_provider)
- self.limits_client = LimitsClientXML(auth_provider)
- self.images_client = ImagesClientXML(auth_provider)
- self.keypairs_client = KeyPairsClientXML(auth_provider)
- self.quotas_client = QuotasClientXML(auth_provider)
- self.flavors_client = FlavorsClientXML(auth_provider)
- self.extensions_client = ExtensionsClientXML(auth_provider)
+ self.auth_provider)
+ self.servers_client = ServersClientXML(self.auth_provider)
+ self.limits_client = LimitsClientXML(self.auth_provider)
+ self.images_client = ImagesClientXML(self.auth_provider)
+ self.keypairs_client = KeyPairsClientXML(self.auth_provider)
+ self.quotas_client = QuotasClientXML(self.auth_provider)
+ self.flavors_client = FlavorsClientXML(self.auth_provider)
+ self.extensions_client = ExtensionsClientXML(self.auth_provider)
self.volumes_extensions_client = VolumesExtensionsClientXML(
- auth_provider)
+ self.auth_provider)
self.floating_ips_client = FloatingIPsClientXML(
- auth_provider)
- self.backups_client = BackupsClientXML(auth_provider)
- self.snapshots_client = SnapshotsClientXML(auth_provider)
- self.volumes_client = VolumesClientXML(auth_provider)
- self.volumes_v2_client = VolumesV2ClientXML(auth_provider)
+ self.auth_provider)
+ self.backups_client = BackupsClientXML(self.auth_provider)
+ self.snapshots_client = SnapshotsClientXML(self.auth_provider)
+ self.volumes_client = VolumesClientXML(self.auth_provider)
+ self.volumes_v2_client = VolumesV2ClientXML(self.auth_provider)
self.volume_types_client = VolumeTypesClientXML(
- auth_provider)
- self.identity_client = IdentityClientXML(auth_provider)
+ self.auth_provider)
+ self.identity_client = IdentityClientXML(self.auth_provider)
self.identity_v3_client = IdentityV3ClientXML(
- auth_provider)
+ self.auth_provider)
self.security_groups_client = SecurityGroupsClientXML(
- auth_provider)
- self.interfaces_client = InterfacesClientXML(auth_provider)
- self.endpoints_client = EndPointClientXML(auth_provider)
- self.fixed_ips_client = FixedIPsClientXML(auth_provider)
+ self.auth_provider)
+ self.interfaces_client = InterfacesClientXML(self.auth_provider)
+ self.endpoints_client = EndPointClientXML(self.auth_provider)
+ self.fixed_ips_client = FixedIPsClientXML(self.auth_provider)
self.availability_zone_client = AvailabilityZoneClientXML(
- auth_provider)
- self.service_client = ServiceClientXML(auth_provider)
- self.aggregates_client = AggregatesClientXML(auth_provider)
- self.services_client = ServicesClientXML(auth_provider)
+ self.auth_provider)
+ self.service_client = ServiceClientXML(self.auth_provider)
+ self.aggregates_client = AggregatesClientXML(self.auth_provider)
+ self.services_client = ServicesClientXML(self.auth_provider)
self.tenant_usages_client = TenantUsagesClientXML(
- auth_provider)
- self.policy_client = PolicyClientXML(auth_provider)
- self.hosts_client = HostsClientXML(auth_provider)
- self.hypervisor_client = HypervisorClientXML(auth_provider)
- self.network_client = NetworkClientXML(auth_provider)
+ self.auth_provider)
+ self.policy_client = PolicyClientXML(self.auth_provider)
+ self.hosts_client = HostsClientXML(self.auth_provider)
+ self.hypervisor_client = HypervisorClientXML(self.auth_provider)
+ self.network_client = NetworkClientXML(self.auth_provider)
self.credentials_client = CredentialsClientXML(
- auth_provider)
+ self.auth_provider)
self.instance_usages_audit_log_client = \
- InstanceUsagesAuditLogClientXML(auth_provider)
+ InstanceUsagesAuditLogClientXML(self.auth_provider)
self.volume_hosts_client = VolumeHostsClientXML(
- auth_provider)
+ self.auth_provider)
self.volumes_extension_client = VolumeExtensionClientXML(
- auth_provider)
+ self.auth_provider)
if CONF.service_available.ceilometer:
self.telemetry_client = TelemetryClientXML(
- auth_provider)
+ self.auth_provider)
self.token_client = TokenClientXML()
self.token_v3_client = V3TokenClientXML()
elif self.interface == 'json':
self.certificates_client = CertificatesClientJSON(
- auth_provider)
+ self.auth_provider)
self.certificates_v3_client = CertificatesV3ClientJSON(
- auth_provider)
- self.baremetal_client = BaremetalClientJSON(auth_provider)
- self.servers_client = ServersClientJSON(auth_provider)
- self.servers_v3_client = ServersV3ClientJSON(auth_provider)
- self.limits_client = LimitsClientJSON(auth_provider)
- self.images_client = ImagesClientJSON(auth_provider)
+ self.auth_provider)
+ self.baremetal_client = BaremetalClientJSON(self.auth_provider)
+ self.servers_client = ServersClientJSON(self.auth_provider)
+ self.servers_v3_client = ServersV3ClientJSON(self.auth_provider)
+ self.limits_client = LimitsClientJSON(self.auth_provider)
+ self.images_client = ImagesClientJSON(self.auth_provider)
self.keypairs_v3_client = KeyPairsV3ClientJSON(
- auth_provider)
- self.keypairs_client = KeyPairsClientJSON(auth_provider)
+ self.auth_provider)
+ self.keypairs_client = KeyPairsClientJSON(self.auth_provider)
self.keypairs_v3_client = KeyPairsV3ClientJSON(
- auth_provider)
- self.quotas_client = QuotasClientJSON(auth_provider)
- self.quotas_v3_client = QuotasV3ClientJSON(auth_provider)
- self.flavors_client = FlavorsClientJSON(auth_provider)
- self.flavors_v3_client = FlavorsV3ClientJSON(auth_provider)
+ self.auth_provider)
+ self.quotas_client = QuotasClientJSON(self.auth_provider)
+ self.quotas_v3_client = QuotasV3ClientJSON(self.auth_provider)
+ self.flavors_client = FlavorsClientJSON(self.auth_provider)
+ self.flavors_v3_client = FlavorsV3ClientJSON(self.auth_provider)
self.extensions_v3_client = ExtensionsV3ClientJSON(
- auth_provider)
+ self.auth_provider)
self.extensions_client = ExtensionsClientJSON(
- auth_provider)
+ self.auth_provider)
self.volumes_extensions_client = VolumesExtensionsClientJSON(
- auth_provider)
+ self.auth_provider)
self.floating_ips_client = FloatingIPsClientJSON(
- auth_provider)
- self.backups_client = BackupsClientJSON(auth_provider)
- self.snapshots_client = SnapshotsClientJSON(auth_provider)
- self.volumes_client = VolumesClientJSON(auth_provider)
- self.volumes_v2_client = VolumesV2ClientJSON(auth_provider)
+ self.auth_provider)
+ self.backups_client = BackupsClientJSON(self.auth_provider)
+ self.snapshots_client = SnapshotsClientJSON(self.auth_provider)
+ self.volumes_client = VolumesClientJSON(self.auth_provider)
+ self.volumes_v2_client = VolumesV2ClientJSON(self.auth_provider)
self.volume_types_client = VolumeTypesClientJSON(
- auth_provider)
- self.identity_client = IdentityClientJSON(auth_provider)
+ self.auth_provider)
+ self.identity_client = IdentityClientJSON(self.auth_provider)
self.identity_v3_client = IdentityV3ClientJSON(
- auth_provider)
+ self.auth_provider)
self.security_groups_client = SecurityGroupsClientJSON(
- auth_provider)
+ self.auth_provider)
self.interfaces_v3_client = InterfacesV3ClientJSON(
- auth_provider)
+ self.auth_provider)
self.interfaces_client = InterfacesClientJSON(
- auth_provider)
- self.endpoints_client = EndPointClientJSON(auth_provider)
- self.fixed_ips_client = FixedIPsClientJSON(auth_provider)
+ self.auth_provider)
+ self.endpoints_client = EndPointClientJSON(self.auth_provider)
+ self.fixed_ips_client = FixedIPsClientJSON(self.auth_provider)
self.availability_zone_v3_client = AvailabilityZoneV3ClientJSON(
- auth_provider)
+ self.auth_provider)
self.availability_zone_client = AvailabilityZoneClientJSON(
- auth_provider)
+ self.auth_provider)
self.services_v3_client = ServicesV3ClientJSON(
- auth_provider)
- self.service_client = ServiceClientJSON(auth_provider)
+ self.auth_provider)
+ self.service_client = ServiceClientJSON(self.auth_provider)
self.aggregates_v3_client = AggregatesV3ClientJSON(
- auth_provider)
+ self.auth_provider)
self.aggregates_client = AggregatesClientJSON(
- auth_provider)
- self.services_client = ServicesClientJSON(auth_provider)
+ self.auth_provider)
+ self.services_client = ServicesClientJSON(self.auth_provider)
self.tenant_usages_client = TenantUsagesClientJSON(
- auth_provider)
- self.version_v3_client = VersionV3ClientJSON(auth_provider)
- self.policy_client = PolicyClientJSON(auth_provider)
- self.hosts_client = HostsClientJSON(auth_provider)
+ self.auth_provider)
+ self.version_v3_client = VersionV3ClientJSON(self.auth_provider)
+ self.policy_client = PolicyClientJSON(self.auth_provider)
+ self.hosts_client = HostsClientJSON(self.auth_provider)
self.hypervisor_v3_client = HypervisorV3ClientJSON(
- auth_provider)
+ self.auth_provider)
self.hypervisor_client = HypervisorClientJSON(
- auth_provider)
- self.network_client = NetworkClientJSON(auth_provider)
+ self.auth_provider)
+ self.network_client = NetworkClientJSON(self.auth_provider)
self.credentials_client = CredentialsClientJSON(
- auth_provider)
+ self.auth_provider)
self.instance_usages_audit_log_client = \
- InstanceUsagesAuditLogClientJSON(auth_provider)
+ InstanceUsagesAuditLogClientJSON(self.auth_provider)
self.volume_hosts_client = VolumeHostsClientJSON(
- auth_provider)
+ self.auth_provider)
self.volumes_extension_client = VolumeExtensionClientJSON(
- auth_provider)
- self.hosts_v3_client = HostsV3ClientJSON(auth_provider)
+ self.auth_provider)
+ self.hosts_v3_client = HostsV3ClientJSON(self.auth_provider)
if CONF.service_available.ceilometer:
self.telemetry_client = TelemetryClientJSON(
- auth_provider)
+ self.auth_provider)
self.token_client = TokenClientJSON()
self.token_v3_client = V3TokenClientJSON()
- self.negative_client = NegativeRestClient(auth_provider)
+ self.negative_client = NegativeRestClient(self.auth_provider)
self.negative_client.service = service
else:
@@ -347,47 +349,22 @@
self.credentials.get('tenant_name'))
# common clients
- self.account_client = AccountClient(auth_provider)
+ self.account_client = AccountClient(self.auth_provider)
if CONF.service_available.glance:
- self.image_client = ImageClientJSON(auth_provider)
- self.image_client_v2 = ImageClientV2JSON(auth_provider)
- self.container_client = ContainerClient(auth_provider)
- self.object_client = ObjectClient(auth_provider)
+ self.image_client = ImageClientJSON(self.auth_provider)
+ self.image_client_v2 = ImageClientV2JSON(self.auth_provider)
+ self.container_client = ContainerClient(self.auth_provider)
+ self.object_client = ObjectClient(self.auth_provider)
self.orchestration_client = OrchestrationClient(
- auth_provider)
+ self.auth_provider)
self.ec2api_client = botoclients.APIClientEC2(*ec2_client_args)
self.s3_client = botoclients.ObjectClientS3(*ec2_client_args)
self.custom_object_client = ObjectClientCustomizedHeader(
- auth_provider)
+ self.auth_provider)
self.custom_account_client = \
- AccountClientCustomizedHeader(auth_provider)
+ AccountClientCustomizedHeader(self.auth_provider)
self.data_processing_client = DataProcessingClient(
- auth_provider)
-
- @classmethod
- def get_auth_provider_class(cls, auth_version):
- if auth_version == 'v2':
- return auth.KeystoneV2AuthProvider
- else:
- return auth.KeystoneV3AuthProvider
-
- def get_default_credentials(self):
- return dict(
- username=CONF.identity.username,
- password=CONF.identity.password,
- tenant_name=CONF.identity.tenant_name
- )
-
- def get_auth_provider(self, credentials=None):
- auth_params = dict(client_type='tempest',
- interface=self.interface)
- auth_provider_class = self.get_auth_provider_class(self.auth_version)
- # If invalid / incomplete credentials are provided, use default ones
- if credentials is None or \
- not auth_provider_class.check_credentials(credentials):
- credentials = self.credentials
- auth_params['credentials'] = credentials
- return auth_provider_class(**auth_params)
+ self.auth_provider)
class AltManager(Manager):
@@ -452,3 +429,187 @@
CONF.identity.tenant_name,
interface=interface,
service=service)
+
+
+class OfficialClientManager(manager.Manager):
+ """
+ Manager that provides access to the official python clients for
+ calling various OpenStack APIs.
+ """
+
+ NOVACLIENT_VERSION = '2'
+ CINDERCLIENT_VERSION = '1'
+ HEATCLIENT_VERSION = '1'
+
+ def __init__(self, username, password, tenant_name):
+ # FIXME(andreaf) Auth provider for client_type 'official' is
+ # not implemented yet, setting to 'tempest' for now.
+ self.client_type = 'tempest'
+ self.interface = None
+ # super cares for credentials validation
+ super(OfficialClientManager, self).__init__(
+ username=username, password=password, tenant_name=tenant_name)
+ self.compute_client = self._get_compute_client(username,
+ password,
+ tenant_name)
+ self.identity_client = self._get_identity_client(username,
+ password,
+ tenant_name)
+ self.image_client = self._get_image_client()
+ self.network_client = self._get_network_client()
+ self.volume_client = self._get_volume_client(username,
+ password,
+ tenant_name)
+ self.object_storage_client = self._get_object_storage_client(
+ username,
+ password,
+ tenant_name)
+ self.orchestration_client = self._get_orchestration_client(
+ username,
+ password,
+ tenant_name)
+
+ def _get_compute_client(self, username, password, tenant_name):
+ # Novaclient will not execute operations for anyone but the
+ # identified user, so a new client needs to be created for
+ # each user that operations need to be performed for.
+ self._validate_credentials(username, password, tenant_name)
+
+ auth_url = CONF.identity.uri
+ dscv = CONF.identity.disable_ssl_certificate_validation
+ region = CONF.identity.region
+
+ client_args = (username, password, tenant_name, auth_url)
+
+ # Create our default Nova client to use in testing
+ service_type = CONF.compute.catalog_type
+ endpoint_type = CONF.compute.endpoint_type
+ return novaclient.client.Client(self.NOVACLIENT_VERSION,
+ *client_args,
+ service_type=service_type,
+ endpoint_type=endpoint_type,
+ region_name=region,
+ no_cache=True,
+ insecure=dscv,
+ http_log_debug=True)
+
+ def _get_image_client(self):
+ token = self.identity_client.auth_token
+ region = CONF.identity.region
+ endpoint_type = CONF.image.endpoint_type
+ endpoint = self.identity_client.service_catalog.url_for(
+ attr='region', filter_value=region,
+ service_type=CONF.image.catalog_type, endpoint_type=endpoint_type)
+ dscv = CONF.identity.disable_ssl_certificate_validation
+ return glanceclient.Client('1', endpoint=endpoint, token=token,
+ insecure=dscv)
+
+ def _get_volume_client(self, username, password, tenant_name):
+ auth_url = CONF.identity.uri
+ region = CONF.identity.region
+ endpoint_type = CONF.volume.endpoint_type
+ return cinderclient.client.Client(self.CINDERCLIENT_VERSION,
+ username,
+ password,
+ tenant_name,
+ auth_url,
+ region_name=region,
+ endpoint_type=endpoint_type,
+ http_log_debug=True)
+
+ def _get_object_storage_client(self, username, password, tenant_name):
+ auth_url = CONF.identity.uri
+ # add current tenant to swift operator role group.
+ keystone_admin = self._get_identity_client(
+ CONF.identity.admin_username,
+ CONF.identity.admin_password,
+ CONF.identity.admin_tenant_name)
+
+ # enable test user to operate swift by adding operator role to him.
+ roles = keystone_admin.roles.list()
+ operator_role = CONF.object_storage.operator_role
+ member_role = [role for role in roles if role.name == operator_role][0]
+ # NOTE(maurosr): This is surrounded in the try-except block cause
+ # neutron tests doesn't have tenant isolation.
+ try:
+ keystone_admin.roles.add_user_role(self.identity_client.user_id,
+ member_role.id,
+ self.identity_client.tenant_id)
+ except keystoneclient.exceptions.Conflict:
+ pass
+
+ endpoint_type = CONF.object_storage.endpoint_type
+ os_options = {'endpoint_type': endpoint_type}
+ return swiftclient.Connection(auth_url, username, password,
+ tenant_name=tenant_name,
+ auth_version='2',
+ os_options=os_options)
+
+ def _get_orchestration_client(self, username=None, password=None,
+ tenant_name=None):
+ if not username:
+ username = CONF.identity.admin_username
+ if not password:
+ password = CONF.identity.admin_password
+ if not tenant_name:
+ tenant_name = CONF.identity.tenant_name
+
+ self._validate_credentials(username, password, tenant_name)
+
+ keystone = self._get_identity_client(username, password, tenant_name)
+ region = CONF.identity.region
+ endpoint_type = CONF.orchestration.endpoint_type
+ token = keystone.auth_token
+ service_type = CONF.orchestration.catalog_type
+ try:
+ endpoint = keystone.service_catalog.url_for(
+ attr='region',
+ filter_value=region,
+ service_type=service_type,
+ endpoint_type=endpoint_type)
+ except keystoneclient.exceptions.EndpointNotFound:
+ return None
+ else:
+ return heatclient.client.Client(self.HEATCLIENT_VERSION,
+ endpoint,
+ token=token,
+ username=username,
+ password=password)
+
+ def _get_identity_client(self, username, password, tenant_name):
+ # This identity client is not intended to check the security
+ # of the identity service, so use admin credentials by default.
+ self._validate_credentials(username, password, tenant_name)
+
+ auth_url = CONF.identity.uri
+ dscv = CONF.identity.disable_ssl_certificate_validation
+
+ return keystoneclient.v2_0.client.Client(username=username,
+ password=password,
+ tenant_name=tenant_name,
+ auth_url=auth_url,
+ insecure=dscv)
+
+ def _get_network_client(self):
+ # The intended configuration is for the network client to have
+ # admin privileges and indicate for whom resources are being
+ # created via a 'tenant_id' parameter. This will often be
+ # preferable to authenticating as a specific user because
+ # working with certain resources (public routers and networks)
+ # often requires admin privileges anyway.
+ username = CONF.identity.admin_username
+ password = CONF.identity.admin_password
+ tenant_name = CONF.identity.admin_tenant_name
+
+ self._validate_credentials(username, password, tenant_name)
+
+ auth_url = CONF.identity.uri
+ dscv = CONF.identity.disable_ssl_certificate_validation
+ endpoint_type = CONF.network.endpoint_type
+
+ return neutronclient.v2_0.client.Client(username=username,
+ password=password,
+ tenant_name=tenant_name,
+ endpoint_type=endpoint_type,
+ auth_url=auth_url,
+ insecure=dscv)
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 5064f07..03dccd4 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -502,24 +502,6 @@
raise NotImplementedError(message)
-class RestClientXML(RestClient):
-
- # NOTE(vponomaryov): This is deprecated class
- # and should be removed after excluding it
- # from all service clients
-
- TYPE = "xml"
-
- def _parse_resp(self, body):
- return xml_to_json(etree.fromstring(body))
-
- def is_absolute_limit(self, resp, resp_body):
- if (not isinstance(resp_body, collections.Mapping) or
- 'retry-after' not in resp):
- return True
- return 'exceed' in resp_body.get('message', 'blabla')
-
-
class NegativeRestClient(RestClient):
"""
Version of RestClient that does not raise exceptions.
diff --git a/tempest/common/utils/test_utils.py b/tempest/common/utils/test_utils.py
index 2e23782..cc0d831 100644
--- a/tempest/common/utils/test_utils.py
+++ b/tempest/common/utils/test_utils.py
@@ -12,9 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest import clients
from tempest.common.utils import misc
from tempest import config
-from tempest.scenario import manager
import json
import re
@@ -35,7 +35,7 @@
self.non_ssh_image_pattern = \
CONF.input_scenario.non_ssh_image_regex
# Setup clients
- ocm = manager.OfficialClientManager(CONF.identity.username,
+ ocm = clients.OfficialClientManager(CONF.identity.username,
CONF.identity.password,
CONF.identity.tenant_name)
self.client = ocm.compute_client
@@ -95,7 +95,7 @@
digit=string.digits)
def __init__(self):
- ocm = manager.OfficialClientManager(CONF.identity.username,
+ ocm = clients.OfficialClientManager(CONF.identity.username,
CONF.identity.password,
CONF.identity.tenant_name)
self.client = ocm.compute_client
diff --git a/tempest/config.py b/tempest/config.py
index a2d35a9..c92a04d 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -343,6 +343,9 @@
cfg.IntOpt('tenant_network_mask_bits',
default=28,
help="The mask bits for tenant ipv4 subnets"),
+ cfg.BoolOpt('ipv6_enabled',
+ default=True,
+ help="Allow the execution of IPv6 tests"),
cfg.StrOpt('tenant_network_v6_cidr',
default="2003::/64",
help="The cidr block to allocate tenant ipv6 subnets from"),
diff --git a/tempest/manager.py b/tempest/manager.py
index 93ff10f..708447e 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -13,8 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest import auth
+from tempest import config
from tempest import exceptions
+CONF = config.CONF
+
class Manager(object):
@@ -25,7 +29,27 @@
and a client object for a test case to use in performing actions.
"""
- def __init__(self):
+ def __init__(self, username=None, password=None, tenant_name=None):
+ """
+ We allow overriding of the credentials used within the various
+ client classes managed by the Manager object. Left as None, the
+ standard username/password/tenant_name[/domain_name] is used.
+
+ :param credentials: Override of the credentials
+ """
+ self.auth_version = CONF.identity.auth_version
+ # FIXME(andreaf) Change Manager __init__ to accept a credentials dict
+ if username is None or password is None:
+ # Tenant None is a valid use case
+ self.credentials = self.get_default_credentials()
+ else:
+ self.credentials = dict(username=username, password=password,
+ tenant_name=tenant_name)
+ if self.auth_version == 'v3':
+ self.credentials['domain_name'] = 'Default'
+ # Creates an auth provider for the credentials
+ self.auth_provider = self.get_auth_provider(self.credentials)
+ # FIXME(andreaf) unused
self.client_attr_names = []
# we do this everywhere, have it be part of the super class
@@ -36,3 +60,28 @@
"tenant_name: %(t)s" %
{'u': username, 'p': password, 't': tenant_name})
raise exceptions.InvalidConfiguration(msg)
+
+ @classmethod
+ def get_auth_provider_class(cls, auth_version):
+ if auth_version == 'v2':
+ return auth.KeystoneV2AuthProvider
+ else:
+ return auth.KeystoneV3AuthProvider
+
+ def get_default_credentials(self):
+ return dict(
+ username=CONF.identity.username,
+ password=CONF.identity.password,
+ tenant_name=CONF.identity.tenant_name
+ )
+
+ def get_auth_provider(self, credentials=None):
+ auth_params = dict(client_type=getattr(self, 'client_type', None),
+ interface=getattr(self, 'interface', None))
+ auth_provider_class = self.get_auth_provider_class(self.auth_version)
+ # If invalid / incomplete credentials are provided, use default ones
+ if credentials is None or \
+ not auth_provider_class.check_credentials(credentials):
+ credentials = self.credentials
+ auth_params['credentials'] = credentials
+ return auth_provider_class(**auth_params)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 4dd51fb..b4fb6ab 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -18,26 +18,17 @@
import os
import subprocess
-# Default client libs
-import cinderclient.client
-import glanceclient
-import heatclient.client
-import keystoneclient.exceptions
-import keystoneclient.v2_0.client
import netaddr
from neutronclient.common import exceptions as exc
-import neutronclient.v2_0.client
-import novaclient.client
from novaclient import exceptions as nova_exceptions
-import swiftclient
from tempest.api.network import common as net_common
+from tempest import clients
from tempest.common import isolated_creds
from tempest.common.utils import data_utils
from tempest.common.utils.linux.remote_client import RemoteClient
from tempest import config
from tempest import exceptions
-import tempest.manager
from tempest.openstack.common import log
import tempest.test
@@ -53,184 +44,6 @@
LOG_cinder_client.addHandler(log.NullHandler())
-class OfficialClientManager(tempest.manager.Manager):
- """
- Manager that provides access to the official python clients for
- calling various OpenStack APIs.
- """
-
- NOVACLIENT_VERSION = '2'
- CINDERCLIENT_VERSION = '1'
- HEATCLIENT_VERSION = '1'
-
- def __init__(self, username, password, tenant_name):
- super(OfficialClientManager, self).__init__()
- self.compute_client = self._get_compute_client(username,
- password,
- tenant_name)
- self.identity_client = self._get_identity_client(username,
- password,
- tenant_name)
- self.image_client = self._get_image_client()
- self.network_client = self._get_network_client()
- self.volume_client = self._get_volume_client(username,
- password,
- tenant_name)
- self.object_storage_client = self._get_object_storage_client(
- username,
- password,
- tenant_name)
- self.orchestration_client = self._get_orchestration_client(
- username,
- password,
- tenant_name)
-
- def _get_compute_client(self, username, password, tenant_name):
- # Novaclient will not execute operations for anyone but the
- # identified user, so a new client needs to be created for
- # each user that operations need to be performed for.
- self._validate_credentials(username, password, tenant_name)
-
- auth_url = CONF.identity.uri
- dscv = CONF.identity.disable_ssl_certificate_validation
- region = CONF.identity.region
-
- client_args = (username, password, tenant_name, auth_url)
-
- # Create our default Nova client to use in testing
- service_type = CONF.compute.catalog_type
- endpoint_type = CONF.compute.endpoint_type
- return novaclient.client.Client(self.NOVACLIENT_VERSION,
- *client_args,
- service_type=service_type,
- endpoint_type=endpoint_type,
- region_name=region,
- no_cache=True,
- insecure=dscv,
- http_log_debug=True)
-
- def _get_image_client(self):
- token = self.identity_client.auth_token
- region = CONF.identity.region
- endpoint_type = CONF.image.endpoint_type
- endpoint = self.identity_client.service_catalog.url_for(
- attr='region', filter_value=region,
- service_type=CONF.image.catalog_type, endpoint_type=endpoint_type)
- dscv = CONF.identity.disable_ssl_certificate_validation
- return glanceclient.Client('1', endpoint=endpoint, token=token,
- insecure=dscv)
-
- def _get_volume_client(self, username, password, tenant_name):
- auth_url = CONF.identity.uri
- region = CONF.identity.region
- endpoint_type = CONF.volume.endpoint_type
- return cinderclient.client.Client(self.CINDERCLIENT_VERSION,
- username,
- password,
- tenant_name,
- auth_url,
- region_name=region,
- endpoint_type=endpoint_type,
- http_log_debug=True)
-
- def _get_object_storage_client(self, username, password, tenant_name):
- auth_url = CONF.identity.uri
- # add current tenant to swift operator role group.
- keystone_admin = self._get_identity_client(
- CONF.identity.admin_username,
- CONF.identity.admin_password,
- CONF.identity.admin_tenant_name)
-
- # enable test user to operate swift by adding operator role to him.
- roles = keystone_admin.roles.list()
- operator_role = CONF.object_storage.operator_role
- member_role = [role for role in roles if role.name == operator_role][0]
- # NOTE(maurosr): This is surrounded in the try-except block cause
- # neutron tests doesn't have tenant isolation.
- try:
- keystone_admin.roles.add_user_role(self.identity_client.user_id,
- member_role.id,
- self.identity_client.tenant_id)
- except keystoneclient.exceptions.Conflict:
- pass
-
- endpoint_type = CONF.object_storage.endpoint_type
- os_options = {'endpoint_type': endpoint_type}
- return swiftclient.Connection(auth_url, username, password,
- tenant_name=tenant_name,
- auth_version='2',
- os_options=os_options)
-
- def _get_orchestration_client(self, username=None, password=None,
- tenant_name=None):
- if not username:
- username = CONF.identity.admin_username
- if not password:
- password = CONF.identity.admin_password
- if not tenant_name:
- tenant_name = CONF.identity.tenant_name
-
- self._validate_credentials(username, password, tenant_name)
-
- keystone = self._get_identity_client(username, password, tenant_name)
- region = CONF.identity.region
- endpoint_type = CONF.orchestration.endpoint_type
- token = keystone.auth_token
- service_type = CONF.orchestration.catalog_type
- try:
- endpoint = keystone.service_catalog.url_for(
- attr='region',
- filter_value=region,
- service_type=service_type,
- endpoint_type=endpoint_type)
- except keystoneclient.exceptions.EndpointNotFound:
- return None
- else:
- return heatclient.client.Client(self.HEATCLIENT_VERSION,
- endpoint,
- token=token,
- username=username,
- password=password)
-
- def _get_identity_client(self, username, password, tenant_name):
- # This identity client is not intended to check the security
- # of the identity service, so use admin credentials by default.
- self._validate_credentials(username, password, tenant_name)
-
- auth_url = CONF.identity.uri
- dscv = CONF.identity.disable_ssl_certificate_validation
-
- return keystoneclient.v2_0.client.Client(username=username,
- password=password,
- tenant_name=tenant_name,
- auth_url=auth_url,
- insecure=dscv)
-
- def _get_network_client(self):
- # The intended configuration is for the network client to have
- # admin privileges and indicate for whom resources are being
- # created via a 'tenant_id' parameter. This will often be
- # preferable to authenticating as a specific user because
- # working with certain resources (public routers and networks)
- # often requires admin privileges anyway.
- username = CONF.identity.admin_username
- password = CONF.identity.admin_password
- tenant_name = CONF.identity.admin_tenant_name
-
- self._validate_credentials(username, password, tenant_name)
-
- auth_url = CONF.identity.uri
- dscv = CONF.identity.disable_ssl_certificate_validation
- endpoint_type = CONF.network.endpoint_type
-
- return neutronclient.v2_0.client.Client(username=username,
- password=password,
- tenant_name=tenant_name,
- endpoint_type=endpoint_type,
- auth_url=auth_url,
- insecure=dscv)
-
-
class OfficialClientTest(tempest.test.BaseTestCase):
"""
Official Client test base class for scenario testing.
@@ -253,7 +66,8 @@
username, password, tenant_name = cls.credentials()
- cls.manager = OfficialClientManager(username, password, tenant_name)
+ cls.manager = clients.OfficialClientManager(
+ username, password, tenant_name)
cls.compute_client = cls.manager.compute_client
cls.image_client = cls.manager.image_client
cls.identity_client = cls.manager.identity_client
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index eabc734..1ddba9e 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -13,13 +13,13 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest import clients
from tempest.common import debug
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest.scenario import manager
-from tempest.scenario.manager import OfficialClientManager
from tempest.test import attr
from tempest.test import call_until_true
from tempest.test import services
@@ -102,7 +102,7 @@
"""
def __init__(self, tenant_id, tenant_user, tenant_pass, tenant_name):
- self.manager = OfficialClientManager(
+ self.manager = clients.OfficialClientManager(
tenant_user,
tenant_pass,
tenant_name
@@ -318,10 +318,13 @@
returns the ip (floating/internal) of a server
"""
if floating:
- return self.floating_ips[server].floating_ip_address
+ server_ip = self.floating_ips[server].floating_ip_address
else:
+ server_ip = None
network_name = self.tenants[server.tenant_id].network.name
- return server.networks[network_name][0]
+ if network_name in server.networks:
+ server_ip = server.networks[network_name][0]
+ return server_ip
def _connect_to_access_point(self, tenant):
"""
diff --git a/tempest/services/botoclients.py b/tempest/services/botoclients.py
index 03e87b1..b52d48c 100644
--- a/tempest/services/botoclients.py
+++ b/tempest/services/botoclients.py
@@ -35,6 +35,7 @@
def __init__(self, username=None, password=None,
auth_url=None, tenant_name=None,
*args, **kwargs):
+ # FIXME(andreaf) replace credentials and auth_url with auth_provider
self.connection_timeout = str(CONF.boto.http_socket_timeout)
self.num_retries = str(CONF.boto.num_retries)
@@ -45,6 +46,7 @@
"tenant_name": tenant_name}
def _keystone_aws_get(self):
+ # FIXME(andreaf) Move EC2 credentials to AuthProvider
import keystoneclient.v2_0.client
keystone = keystoneclient.v2_0.client.Client(**self.ks_cred)
diff --git a/tempest/services/compute/xml/aggregates_client.py b/tempest/services/compute/xml/aggregates_client.py
index cf853ba..5b250ee 100644
--- a/tempest/services/compute/xml/aggregates_client.py
+++ b/tempest/services/compute/xml/aggregates_client.py
@@ -15,7 +15,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest.services.compute.xml.common import Document
@@ -26,7 +26,8 @@
CONF = config.CONF
-class AggregatesClientXML(RestClientXML):
+class AggregatesClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(AggregatesClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/availability_zone_client.py b/tempest/services/compute/xml/availability_zone_client.py
index 3d8ac8a..4d71186 100644
--- a/tempest/services/compute/xml/availability_zone_client.py
+++ b/tempest/services/compute/xml/availability_zone_client.py
@@ -15,14 +15,15 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import xml_to_json
CONF = config.CONF
-class AvailabilityZoneClientXML(RestClientXML):
+class AvailabilityZoneClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(AvailabilityZoneClientXML, self).__init__(
diff --git a/tempest/services/compute/xml/certificates_client.py b/tempest/services/compute/xml/certificates_client.py
index 4ee10c4..24ffca8 100644
--- a/tempest/services/compute/xml/certificates_client.py
+++ b/tempest/services/compute/xml/certificates_client.py
@@ -14,13 +14,14 @@
# under the License.
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class CertificatesClientXML(RestClientXML):
+class CertificatesClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(CertificatesClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/extensions_client.py b/tempest/services/compute/xml/extensions_client.py
index f97b64d..3e8254c 100644
--- a/tempest/services/compute/xml/extensions_client.py
+++ b/tempest/services/compute/xml/extensions_client.py
@@ -15,14 +15,15 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import xml_to_json
CONF = config.CONF
-class ExtensionsClientXML(RestClientXML):
+class ExtensionsClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(ExtensionsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/fixed_ips_client.py b/tempest/services/compute/xml/fixed_ips_client.py
index b89e096..0475530 100644
--- a/tempest/services/compute/xml/fixed_ips_client.py
+++ b/tempest/services/compute/xml/fixed_ips_client.py
@@ -14,7 +14,7 @@
# under the License.
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -23,7 +23,8 @@
CONF = config.CONF
-class FixedIPsClientXML(RestClientXML):
+class FixedIPsClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(FixedIPsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/flavors_client.py b/tempest/services/compute/xml/flavors_client.py
index 554b253..68a27c9 100644
--- a/tempest/services/compute/xml/flavors_client.py
+++ b/tempest/services/compute/xml/flavors_client.py
@@ -17,7 +17,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -33,7 +33,8 @@
"http://docs.openstack.org/compute/ext/flavor_access/api/v2"
-class FlavorsClientXML(RestClientXML):
+class FlavorsClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(FlavorsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/floating_ips_client.py b/tempest/services/compute/xml/floating_ips_client.py
index d6decf3..be54753 100644
--- a/tempest/services/compute/xml/floating_ips_client.py
+++ b/tempest/services/compute/xml/floating_ips_client.py
@@ -16,7 +16,7 @@
from lxml import etree
import urllib
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest.services.compute.xml.common import Document
@@ -27,7 +27,9 @@
CONF = config.CONF
-class FloatingIPsClientXML(RestClientXML):
+class FloatingIPsClientXML(rest_client.RestClient):
+ TYPE = "xml"
+
def __init__(self, auth_provider):
super(FloatingIPsClientXML, self).__init__(auth_provider)
self.service = CONF.compute.catalog_type
diff --git a/tempest/services/compute/xml/hosts_client.py b/tempest/services/compute/xml/hosts_client.py
index 13abe18..b74cd04 100644
--- a/tempest/services/compute/xml/hosts_client.py
+++ b/tempest/services/compute/xml/hosts_client.py
@@ -15,7 +15,7 @@
import urllib
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -24,7 +24,8 @@
CONF = config.CONF
-class HostsClientXML(RestClientXML):
+class HostsClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(HostsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/hypervisor_client.py b/tempest/services/compute/xml/hypervisor_client.py
index 3c1ef08..ecd7541 100644
--- a/tempest/services/compute/xml/hypervisor_client.py
+++ b/tempest/services/compute/xml/hypervisor_client.py
@@ -15,14 +15,15 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import xml_to_json
CONF = config.CONF
-class HypervisorClientXML(RestClientXML):
+class HypervisorClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(HypervisorClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/images_client.py b/tempest/services/compute/xml/images_client.py
index 9f80c55..9d529be 100644
--- a/tempest/services/compute/xml/images_client.py
+++ b/tempest/services/compute/xml/images_client.py
@@ -17,7 +17,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest.common import waiters
from tempest import config
from tempest import exceptions
@@ -30,7 +30,8 @@
CONF = config.CONF
-class ImagesClientXML(RestClientXML):
+class ImagesClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(ImagesClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/instance_usage_audit_log_client.py b/tempest/services/compute/xml/instance_usage_audit_log_client.py
index baa6966..1cd8c07 100644
--- a/tempest/services/compute/xml/instance_usage_audit_log_client.py
+++ b/tempest/services/compute/xml/instance_usage_audit_log_client.py
@@ -15,14 +15,15 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import xml_to_json
CONF = config.CONF
-class InstanceUsagesAuditLogClientXML(RestClientXML):
+class InstanceUsagesAuditLogClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(InstanceUsagesAuditLogClientXML, self).__init__(
diff --git a/tempest/services/compute/xml/interfaces_client.py b/tempest/services/compute/xml/interfaces_client.py
index 6155cd6..5df6187 100644
--- a/tempest/services/compute/xml/interfaces_client.py
+++ b/tempest/services/compute/xml/interfaces_client.py
@@ -17,7 +17,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest.services.compute.xml.common import Document
@@ -28,7 +28,8 @@
CONF = config.CONF
-class InterfacesClientXML(RestClientXML):
+class InterfacesClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(InterfacesClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/keypairs_client.py b/tempest/services/compute/xml/keypairs_client.py
index 5641251..fb498c0 100644
--- a/tempest/services/compute/xml/keypairs_client.py
+++ b/tempest/services/compute/xml/keypairs_client.py
@@ -16,7 +16,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -26,7 +26,8 @@
CONF = config.CONF
-class KeyPairsClientXML(RestClientXML):
+class KeyPairsClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(KeyPairsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/limits_client.py b/tempest/services/compute/xml/limits_client.py
index 61c434c..2327626 100644
--- a/tempest/services/compute/xml/limits_client.py
+++ b/tempest/services/compute/xml/limits_client.py
@@ -15,7 +15,7 @@
from lxml import objectify
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
@@ -23,7 +23,8 @@
NS = "{http://docs.openstack.org/common/api/v1.0}"
-class LimitsClientXML(RestClientXML):
+class LimitsClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(LimitsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/quotas_client.py b/tempest/services/compute/xml/quotas_client.py
index 00c3275..eb287c2 100644
--- a/tempest/services/compute/xml/quotas_client.py
+++ b/tempest/services/compute/xml/quotas_client.py
@@ -15,7 +15,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -25,7 +25,8 @@
CONF = config.CONF
-class QuotasClientXML(RestClientXML):
+class QuotasClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(QuotasClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/security_groups_client.py b/tempest/services/compute/xml/security_groups_client.py
index 947f6da..d53e8da 100644
--- a/tempest/services/compute/xml/security_groups_client.py
+++ b/tempest/services/compute/xml/security_groups_client.py
@@ -16,7 +16,7 @@
from lxml import etree
import urllib
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest.services.compute.xml.common import Document
@@ -28,7 +28,8 @@
CONF = config.CONF
-class SecurityGroupsClientXML(RestClientXML):
+class SecurityGroupsClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(SecurityGroupsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/servers_client.py b/tempest/services/compute/xml/servers_client.py
index a182d35..da01b83 100644
--- a/tempest/services/compute/xml/servers_client.py
+++ b/tempest/services/compute/xml/servers_client.py
@@ -19,7 +19,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest.common import waiters
from tempest import config
from tempest import exceptions
@@ -139,7 +139,8 @@
return json
-class ServersClientXML(RestClientXML):
+class ServersClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(ServersClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/services_client.py b/tempest/services/compute/xml/services_client.py
index 5943ea9..d7b8a60 100644
--- a/tempest/services/compute/xml/services_client.py
+++ b/tempest/services/compute/xml/services_client.py
@@ -18,7 +18,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -27,7 +27,8 @@
CONF = config.CONF
-class ServicesClientXML(RestClientXML):
+class ServicesClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(ServicesClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/tenant_usages_client.py b/tempest/services/compute/xml/tenant_usages_client.py
index 96c3147..79f0ac9 100644
--- a/tempest/services/compute/xml/tenant_usages_client.py
+++ b/tempest/services/compute/xml/tenant_usages_client.py
@@ -17,14 +17,15 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import xml_to_json
CONF = config.CONF
-class TenantUsagesClientXML(RestClientXML):
+class TenantUsagesClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(TenantUsagesClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/compute/xml/volumes_extensions_client.py b/tempest/services/compute/xml/volumes_extensions_client.py
index a43fc21..570b715 100644
--- a/tempest/services/compute/xml/volumes_extensions_client.py
+++ b/tempest/services/compute/xml/volumes_extensions_client.py
@@ -18,7 +18,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest.services.compute.xml.common import Document
@@ -30,7 +30,8 @@
CONF = config.CONF
-class VolumesExtensionsClientXML(RestClientXML):
+class VolumesExtensionsClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(VolumesExtensionsClientXML, self).__init__(
diff --git a/tempest/services/identity/v3/xml/credentials_client.py b/tempest/services/identity/v3/xml/credentials_client.py
index f6fa678..22ed44d 100644
--- a/tempest/services/identity/v3/xml/credentials_client.py
+++ b/tempest/services/identity/v3/xml/credentials_client.py
@@ -17,7 +17,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -29,7 +29,8 @@
XMLNS = "http://docs.openstack.org/identity/api/v3"
-class CredentialsClientXML(RestClientXML):
+class CredentialsClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(CredentialsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/identity/v3/xml/endpoints_client.py b/tempest/services/identity/v3/xml/endpoints_client.py
index 2a88c15..a32eede 100644
--- a/tempest/services/identity/v3/xml/endpoints_client.py
+++ b/tempest/services/identity/v3/xml/endpoints_client.py
@@ -16,7 +16,7 @@
from lxml import etree
from tempest.common import http
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -27,7 +27,8 @@
XMLNS = "http://docs.openstack.org/identity/api/v3"
-class EndPointClientXML(RestClientXML):
+class EndPointClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(EndPointClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/identity/v3/xml/identity_client.py b/tempest/services/identity/v3/xml/identity_client.py
index 5ae0461..e8e70d8 100644
--- a/tempest/services/identity/v3/xml/identity_client.py
+++ b/tempest/services/identity/v3/xml/identity_client.py
@@ -17,7 +17,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest.services.compute.xml.common import Document
@@ -30,7 +30,8 @@
XMLNS = "http://docs.openstack.org/identity/api/v3"
-class IdentityV3ClientXML(RestClientXML):
+class IdentityV3ClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(IdentityV3ClientXML, self).__init__(auth_provider)
@@ -426,7 +427,8 @@
return resp, body
-class V3TokenClientXML(RestClientXML):
+class V3TokenClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self):
super(V3TokenClientXML, self).__init__(None)
diff --git a/tempest/services/identity/v3/xml/policy_client.py b/tempest/services/identity/v3/xml/policy_client.py
index a7e63a7..c12018a 100644
--- a/tempest/services/identity/v3/xml/policy_client.py
+++ b/tempest/services/identity/v3/xml/policy_client.py
@@ -16,7 +16,7 @@
from lxml import etree
from tempest.common import http
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -27,7 +27,8 @@
XMLNS = "http://docs.openstack.org/identity/api/v3"
-class PolicyClientXML(RestClientXML):
+class PolicyClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(PolicyClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/identity/v3/xml/service_client.py b/tempest/services/identity/v3/xml/service_client.py
index be6c443..d5476c4 100644
--- a/tempest/services/identity/v3/xml/service_client.py
+++ b/tempest/services/identity/v3/xml/service_client.py
@@ -15,7 +15,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -26,7 +26,8 @@
XMLNS = "http://docs.openstack.org/identity/api/v3"
-class ServiceClientXML(RestClientXML):
+class ServiceClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(ServiceClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/network/xml/network_client.py b/tempest/services/network/xml/network_client.py
index 5f3f8c1..f6ae718 100644
--- a/tempest/services/network/xml/network_client.py
+++ b/tempest/services/network/xml/network_client.py
@@ -13,7 +13,7 @@
from lxml import etree
import xml.etree.ElementTree as ET
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest.services.compute.xml.common import deep_dict_to_xml
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
@@ -23,13 +23,16 @@
class NetworkClientXML(client_base.NetworkClientBase):
+ TYPE = "xml"
# list of plurals used for xml serialization
PLURALS = ['dns_nameservers', 'host_routes', 'allocation_pools',
'fixed_ips', 'extensions', 'extra_dhcp_opts']
def get_rest_client(self, auth_provider):
- return RestClientXML(auth_provider)
+ rc = rest_client.RestClient(auth_provider)
+ rc.TYPE = self.TYPE
+ return rc
def _parse_array(self, node):
array = []
diff --git a/tempest/services/telemetry/xml/telemetry_client.py b/tempest/services/telemetry/xml/telemetry_client.py
index f29fe22..165f29a 100644
--- a/tempest/services/telemetry/xml/telemetry_client.py
+++ b/tempest/services/telemetry/xml/telemetry_client.py
@@ -15,16 +15,19 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import xml_to_json
import tempest.services.telemetry.telemetry_client_base as client
class TelemetryClientXML(client.TelemetryClientBase):
+ TYPE = "xml"
def get_rest_client(self, auth_provider):
- return RestClientXML(auth_provider)
+ rc = rest_client.RestClient(auth_provider)
+ rc.TYPE = self.TYPE
+ return rc
def _parse_array(self, body):
array = []
diff --git a/tempest/services/volume/v2/xml/volumes_client.py b/tempest/services/volume/v2/xml/volumes_client.py
index 69e3f5b..bc57842 100644
--- a/tempest/services/volume/v2/xml/volumes_client.py
+++ b/tempest/services/volume/v2/xml/volumes_client.py
@@ -18,7 +18,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest.services.compute.xml.common import Document
@@ -30,10 +30,11 @@
CONF = config.CONF
-class VolumesV2ClientXML(RestClientXML):
+class VolumesV2ClientXML(rest_client.RestClient):
"""
Client class to send CRUD Volume API requests to a Cinder endpoint
"""
+ TYPE = "xml"
def __init__(self, auth_provider):
super(VolumesV2ClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/volume/xml/admin/volume_hosts_client.py b/tempest/services/volume/xml/admin/volume_hosts_client.py
index 080e3d1..fb84c83 100644
--- a/tempest/services/volume/xml/admin/volume_hosts_client.py
+++ b/tempest/services/volume/xml/admin/volume_hosts_client.py
@@ -17,17 +17,18 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import xml_to_json
CONF = config.CONF
-class VolumeHostsClientXML(RestClientXML):
+class VolumeHostsClientXML(rest_client.RestClient):
"""
Client class to send CRUD Volume Hosts API requests to a Cinder endpoint
"""
+ TYPE = "xml"
def __init__(self, auth_provider):
super(VolumeHostsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/volume/xml/admin/volume_types_client.py b/tempest/services/volume/xml/admin/volume_types_client.py
index 802d27a..77bafec 100644
--- a/tempest/services/volume/xml/admin/volume_types_client.py
+++ b/tempest/services/volume/xml/admin/volume_types_client.py
@@ -17,7 +17,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest.services.compute.xml.common import Document
@@ -29,10 +29,11 @@
CONF = config.CONF
-class VolumeTypesClientXML(RestClientXML):
+class VolumeTypesClientXML(rest_client.RestClient):
"""
Client class to send CRUD Volume Types API requests to a Cinder endpoint
"""
+ TYPE = "xml"
def __init__(self, auth_provider):
super(VolumeTypesClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/volume/xml/backups_client.py b/tempest/services/volume/xml/backups_client.py
index 6a71f8b..81caaee 100644
--- a/tempest/services/volume/xml/backups_client.py
+++ b/tempest/services/volume/xml/backups_client.py
@@ -13,13 +13,14 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.common.rest_client import RestClientXML
+from tempest.services.volume.json import backups_client
-class BackupsClientXML(RestClientXML):
+class BackupsClientXML(backups_client.BackupsClientJSON):
"""
Client class to send CRUD Volume Backup API requests to a Cinder endpoint
"""
+ TYPE = "xml"
#TODO(gfidente): XML client isn't yet implemented because of bug 1270589
pass
diff --git a/tempest/services/volume/xml/extensions_client.py b/tempest/services/volume/xml/extensions_client.py
index 03743a6..1ea974f 100644
--- a/tempest/services/volume/xml/extensions_client.py
+++ b/tempest/services/volume/xml/extensions_client.py
@@ -15,14 +15,15 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest.services.compute.xml.common import xml_to_json
CONF = config.CONF
-class ExtensionsClientXML(RestClientXML):
+class ExtensionsClientXML(rest_client.RestClient):
+ TYPE = "xml"
def __init__(self, auth_provider):
super(ExtensionsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/volume/xml/snapshots_client.py b/tempest/services/volume/xml/snapshots_client.py
index 9abe042..458001b 100644
--- a/tempest/services/volume/xml/snapshots_client.py
+++ b/tempest/services/volume/xml/snapshots_client.py
@@ -15,7 +15,7 @@
from lxml import etree
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest.openstack.common import log as logging
@@ -30,8 +30,9 @@
LOG = logging.getLogger(__name__)
-class SnapshotsClientXML(RestClientXML):
+class SnapshotsClientXML(rest_client.RestClient):
"""Client class to send CRUD Volume API requests."""
+ TYPE = "xml"
def __init__(self, auth_provider):
super(SnapshotsClientXML, self).__init__(auth_provider)
diff --git a/tempest/services/volume/xml/volumes_client.py b/tempest/services/volume/xml/volumes_client.py
index 94c1ff6..aef1e3c 100644
--- a/tempest/services/volume/xml/volumes_client.py
+++ b/tempest/services/volume/xml/volumes_client.py
@@ -19,7 +19,7 @@
from lxml import etree
from xml.sax.saxutils import escape
-from tempest.common.rest_client import RestClientXML
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest.services.compute.xml.common import Document
@@ -31,10 +31,11 @@
CONF = config.CONF
-class VolumesClientXML(RestClientXML):
+class VolumesClientXML(rest_client.RestClient):
"""
Client class to send CRUD Volume API requests to a Cinder endpoint
"""
+ TYPE = "xml"
def __init__(self, auth_provider):
super(VolumesClientXML, self).__init__(auth_provider)
diff --git a/tempest/stress/run_stress.py b/tempest/stress/run_stress.py
index 76320d0..a6c2b77 100755
--- a/tempest/stress/run_stress.py
+++ b/tempest/stress/run_stress.py
@@ -87,8 +87,13 @@
# NOTE(mkoderer): we just save the last result code
if (step_result != 0):
result = step_result
+ if ns.stop:
+ return result
else:
- driver.stress_openstack(tests, ns.duration, ns.number, ns.stop)
+ result = driver.stress_openstack(tests,
+ ns.duration,
+ ns.number,
+ ns.stop)
return result