Merge "change ipv6 public network cidr on tempest-slow job"
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index c1981f9..06062c2 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -302,6 +302,10 @@
.. _2.2: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id2
+ * `2.3`_
+
+ .. _2.3: http://docs.openstack.org/developer/nova/api_microversion_history.html#maximum-in-kilo
+
* `2.6`_
.. _2.6: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id5
diff --git a/releasenotes/notes/Add-keystone-v3-OS_FEDERATION-APIs-as-tempest-clients-fe9e10a0fe5f09d4.yaml b/releasenotes/notes/Add-keystone-v3-OS_FEDERATION-APIs-as-tempest-clients-fe9e10a0fe5f09d4.yaml
new file mode 100644
index 0000000..33df7c4
--- /dev/null
+++ b/releasenotes/notes/Add-keystone-v3-OS_FEDERATION-APIs-as-tempest-clients-fe9e10a0fe5f09d4.yaml
@@ -0,0 +1,10 @@
+---
+features:
+ - |
+ The following tempest clients for keystone v3 OS_FEDERATION API were
+ implemented in this release
+
+ * identity_providers
+ * protocols
+ * mappings
+ * service_providers
diff --git a/releasenotes/notes/Remove-manager-2e0b0af48f01294a.yaml b/releasenotes/notes/Remove-manager-2e0b0af48f01294a.yaml
new file mode 100644
index 0000000..822df7d
--- /dev/null
+++ b/releasenotes/notes/Remove-manager-2e0b0af48f01294a.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+ - |
+ In this release tempest/manager.py is removed after more than 4 years
+ of deprecation.
diff --git a/releasenotes/notes/create_loginable_secgroup_rule-73722fd4b4eb12d0.yaml b/releasenotes/notes/create_loginable_secgroup_rule-73722fd4b4eb12d0.yaml
new file mode 100644
index 0000000..e53411d
--- /dev/null
+++ b/releasenotes/notes/create_loginable_secgroup_rule-73722fd4b4eb12d0.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Added public interface create_loginable_secgroup_rule().
+ Since this interface is meant to be used by tempest plugins,
+ It doesn't neccessarily require to be private api.
diff --git a/releasenotes/notes/create_security_group_rule-16d58a8f0f0ff262.yaml b/releasenotes/notes/create_security_group_rule-16d58a8f0f0ff262.yaml
new file mode 100644
index 0000000..3354f65
--- /dev/null
+++ b/releasenotes/notes/create_security_group_rule-16d58a8f0f0ff262.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Added public interface create_security_group_rule().
+ Since this interface is meant to be used by tempest plugins,
+ It doesn't neccessarily require to be private api.
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index 0296220..275a26f 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -110,20 +110,30 @@
Creating another server image when first image is being saved is
not allowed.
"""
- # Create first snapshot
- image = self.create_image_from_server(self.server_id)
- self.addCleanup(self._reset_server)
+ try:
+ # Create first snapshot
+ image = self.create_image_from_server(self.server_id)
+ self.addCleanup(self._reset_server)
- # Create second snapshot
- self.assertRaises(lib_exc.Conflict, self.create_image_from_server,
- self.server_id)
+ # Create second snapshot
+ self.assertRaises(lib_exc.Conflict, self.create_image_from_server,
+ self.server_id)
- if api_version_utils.compare_version_header_to_response(
- "OpenStack-API-Version", "compute 2.45", image.response, "lt"):
- image_id = image['image_id']
- else:
- image_id = data_utils.parse_image_id(image.response['location'])
- self.client.delete_image(image_id)
+ if api_version_utils.compare_version_header_to_response(
+ "OpenStack-API-Version", "compute 2.45", image.response, "lt"):
+ image_id = image['image_id']
+ else:
+ image_id = data_utils.parse_image_id(
+ image.response['location'])
+ self.client.delete_image(image_id)
+
+ except lib_exc.TimeoutException as ex:
+ # Test cannot capture the image saving state.
+ # If timeout is reached, we don't need to check state,
+ # since, it wouldn't be a 'SAVING' state atleast and apart from
+ # it, this testcase doesn't have scope for other state transition
+ # Hence, skip the test.
+ raise self.skipException("This test is skipped because " + str(ex))
@decorators.attr(type=['negative'])
@decorators.idempotent_id('084f0cbc-500a-4963-8a4e-312905862581')
diff --git a/tempest/config.py b/tempest/config.py
index 956b593..31d9b1b 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -1207,6 +1207,39 @@
help="Whether or not horizon is expected to be available"),
]
+enforce_scope_group = cfg.OptGroup(name="enforce_scope",
+ title="OpenStack Services with "
+ "enforce scope")
+
+
+EnforceScopeGroup = [
+ cfg.BoolOpt('nova',
+ default=False,
+ help='Does the compute service API policies enforce scope? '
+ 'This configuration value should be same as '
+ 'nova.conf: [oslo_policy].enforce_scope option.'),
+ cfg.BoolOpt('neutron',
+ default=False,
+ help='Does the network service API policies enforce scope? '
+ 'This configuration value should be same as '
+ 'neutron.conf: [oslo_policy].enforce_scope option.'),
+ cfg.BoolOpt('glance',
+ default=False,
+ help='Does the Image service API policies enforce scope? '
+ 'This configuration value should be same as '
+ 'glance.conf: [oslo_policy].enforce_scope option.'),
+ cfg.BoolOpt('cinder',
+ default=False,
+ help='Does the Volume service API policies enforce scope? '
+ 'This configuration value should be same as '
+ 'cinder.conf: [oslo_policy].enforce_scope option.'),
+ cfg.BoolOpt('keystone',
+ default=False,
+ help='Does the Identity service API policies enforce scope? '
+ 'This configuration value should be same as '
+ 'keystone.conf: [oslo_policy].enforce_scope option.'),
+]
+
debug_group = cfg.OptGroup(name="debug",
title="Debug System")
@@ -1276,6 +1309,7 @@
(object_storage_feature_group, ObjectStoreFeaturesGroup),
(scenario_group, ScenarioGroup),
(service_available_group, ServiceAvailableGroup),
+ (enforce_scope_group, EnforceScopeGroup),
(debug_group, DebugGroup),
(placement_group, PlacementGroup),
(profiler_group, ProfilerGroup),
@@ -1345,6 +1379,7 @@
'object-storage-feature-enabled']
self.scenario = _CONF.scenario
self.service_available = _CONF.service_available
+ self.enforce_scope = _CONF.enforce_scope
self.debug = _CONF.debug
logging.tempest_set_log_file('tempest.log')
# Setting attributes for plugins
diff --git a/tempest/lib/decorators.py b/tempest/lib/decorators.py
index ebe2d61..25ff473 100644
--- a/tempest/lib/decorators.py
+++ b/tempest/lib/decorators.py
@@ -72,19 +72,13 @@
def decorator(f):
@functools.wraps(f)
def wrapper(*func_args, **func_kwargs):
- skip = False
- msg = ''
- if "condition" in kwargs:
- if kwargs["condition"] is True:
- skip = True
- else:
- skip = True
- if "bug" in kwargs and skip is True:
- bug = kwargs['bug']
+ condition = kwargs.get('condition', True)
+ bug = kwargs.get('bug', None)
+ if bug and condition:
bug_type = kwargs.get('bug_type', 'launchpad')
bug_url = _get_bug_url(bug, bug_type)
- msg = "Skipped until bug: %s is resolved." % bug_url
- raise testtools.TestCase.skipException(msg)
+ raise testtools.TestCase.skipException(
+ "Skipped until bug: %s is resolved." % bug_url)
return f(*func_args, **func_kwargs)
return wrapper
return decorator
diff --git a/tempest/lib/services/identity/v3/identity_providers_client.py b/tempest/lib/services/identity/v3/identity_providers_client.py
new file mode 100644
index 0000000..af6a245
--- /dev/null
+++ b/tempest/lib/services/identity/v3/identity_providers_client.py
@@ -0,0 +1,92 @@
+# Copyright 2020 Samsung Electronics Co., Ltd
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.lib.common import rest_client
+
+
+class IdentityProvidersClient(rest_client.RestClient):
+
+ def register_identity_provider(self, identity_provider_id, **kwargs):
+ """Register an identity provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#register-an-identity-provider
+ """
+ post_body = json.dumps({'identity_provider': kwargs})
+ resp, body = self.put(
+ 'OS-FEDERATION/identity_providers/%s' % identity_provider_id,
+ post_body)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_identity_providers(self, **params):
+ """List identity providers.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#list-identity-providers
+ """
+ url = 'identity_providers'
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def get_identity_provider(self, identity_provider_id):
+ """Get identity provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#get-identity-provider
+ """
+ resp, body = self.get(
+ 'OS-FEDERATION/identity_providers/%s' % identity_provider_id)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_identity_provider(self, identity_provider_id):
+ """Delete identity provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#delete-identity-provider
+ """
+ resp, body = self.delete(
+ 'OS-FEDERATION/identity_providers/%s' % identity_provider_id)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_identity_provider(self, identity_provider_id, **kwargs):
+ """Update identity provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#update-identity-provider
+ """
+ post_body = json.dumps({'identity_provider': kwargs})
+ resp, body = self.patch(
+ 'OS-FEDERATION/identity_providers/%s' % identity_provider_id,
+ post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/identity/v3/mappings_client.py b/tempest/lib/services/identity/v3/mappings_client.py
new file mode 100644
index 0000000..9ec5384
--- /dev/null
+++ b/tempest/lib/services/identity/v3/mappings_client.py
@@ -0,0 +1,90 @@
+# Copyright 2020 Samsung Electronics Co., Ltd
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.lib.common import rest_client
+
+
+class MappingsClient(rest_client.RestClient):
+
+ def create_mapping(self, mapping_id, **kwargs):
+ """Create a mapping.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#create-a-mapping
+ """
+ post_body = json.dumps({'mapping': kwargs})
+ resp, body = self.put(
+ 'OS-FEDERATION/mappings/%s' % mapping_id, post_body)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def get_mapping(self, mapping_id):
+ """Get a mapping.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#get-a-mapping
+ """
+ resp, body = self.get(
+ 'OS-FEDERATION/mappings/%s' % mapping_id)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_mapping(self, mapping_id, **kwargs):
+ """Update a mapping.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#update-a-mapping
+ """
+ post_body = json.dumps({'mapping': kwargs})
+ resp, body = self.patch(
+ 'OS-FEDERATION/mappings/%s' % mapping_id, post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_mappings(self, **kwargs):
+ """List mappings.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#list-mappings
+ """
+ url = 'OS-FEDERATION/mappings'
+ if kwargs:
+ url += '?%s' % urllib.urlencode(kwargs)
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_mapping(self, mapping_id):
+ """Delete a mapping.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#delete-a-mapping
+ """
+ resp, body = self.delete(
+ 'OS-FEDERATION/mappings/%s' % mapping_id)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/identity/v3/protocols_client.py b/tempest/lib/services/identity/v3/protocols_client.py
new file mode 100644
index 0000000..2e0221b
--- /dev/null
+++ b/tempest/lib/services/identity/v3/protocols_client.py
@@ -0,0 +1,96 @@
+# Copyright 2020 Samsung Electronics Co., Ltd
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.lib.common import rest_client
+
+
+class ProtocolsClient(rest_client.RestClient):
+
+ def add_protocol_to_identity_provider(self, idp_id, protocol_id,
+ **kwargs):
+ """Add protocol to identity provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#add-protocol-to-identity-provider
+ """
+ post_body = json.dumps({'protocol': kwargs})
+ resp, body = self.put(
+ 'OS-FEDERATION/identity_providers/%s/protocols/%s'
+ % (idp_id, protocol_id), post_body)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_protocols_of_identity_provider(self, idp_id, **kwargs):
+ """List protocols of identity provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#list-protocols-of-identity-provider
+ """
+ url = 'OS-FEDERATION/identity_providers/%s/protocols' % idp_id
+ if kwargs:
+ url += '?%s' % urllib.urlencode(kwargs)
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def get_protocol_for_identity_provider(self, idp_id, protocol_id):
+ """Get protocol for identity provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#get-protocol-for-identity-provider
+ """
+ resp, body = self.get(
+ 'OS-FEDERATION/identity_providers/%s/protocols/%s'
+ % (idp_id, protocol_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_mapping_for_identity_provider(self, idp_id, protocol_id,
+ **kwargs):
+ """Update attribute mapping for identity provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#update-attribute-mapping-for-identity-provider
+ """
+ post_body = json.dumps({'protocol': kwargs})
+ resp, body = self.patch(
+ 'OS-FEDERATION/identity_providers/%s/protocols/%s'
+ % (idp_id, protocol_id), post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_protocol_from_identity_provider(self, idp_id, protocol_id):
+ """Delete a protocol from identity provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#delete-a-protocol-from-identity-provider
+ """
+ resp, body = self.delete(
+ 'OS-FEDERATION/identity_providers/%s/protocols/%s'
+ % (idp_id, protocol_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/identity/v3/service_providers_client.py b/tempest/lib/services/identity/v3/service_providers_client.py
new file mode 100644
index 0000000..b84cf43
--- /dev/null
+++ b/tempest/lib/services/identity/v3/service_providers_client.py
@@ -0,0 +1,92 @@
+# Copyright 2020 Samsung Electronics Co., Ltd
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.lib.common import rest_client
+
+
+class ServiceProvidersClient(rest_client.RestClient):
+
+ def register_service_provider(self, service_provider_id, **kwargs):
+ """Register a service provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#register-a-service-provider
+ """
+ post_body = json.dumps({'service_provider': kwargs})
+ resp, body = self.put(
+ 'OS-FEDERATION/service_providers/%s' % service_provider_id,
+ post_body)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_service_providers(self, **kwargs):
+ """List service providers.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#list-service-providers
+ """
+ url = 'OS-FEDERATION/service_providers'
+ if kwargs:
+ url += '?%s' % urllib.urlencode(kwargs)
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def get_service_provider(self, service_provider_id):
+ """Get a service provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#get-service-provider
+ """
+ resp, body = self.get(
+ 'OS-FEDERATION/service_providers/%s' % service_provider_id)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_service_provider(self, service_provider_id):
+ """Delete a service provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#delete-service-provider
+ """
+ resp, body = self.delete(
+ 'OS-FEDERATION/service_providers/%s' % service_provider_id)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_service_provider(self, service_provider_id, **kwargs):
+ """Update a service provider.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/identity/v3-ext/index.html#update-service-provider
+ """
+ post_body = json.dumps({'service_provider': kwargs})
+ resp, body = self.patch(
+ 'OS-FEDERATION/service_providers/%s' % service_provider_id,
+ post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/manager.py b/tempest/manager.py
deleted file mode 100644
index b485ef2..0000000
--- a/tempest/manager.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_log import log as logging
-
-from tempest import clients as tempest_clients
-from tempest import config
-from tempest.lib.services import clients
-
-CONF = config.CONF
-LOG = logging.getLogger(__name__)
-
-
-class Manager(clients.ServiceClients):
- """Service client manager class for backward compatibility
-
- The former manager.Manager is not a stable interface in Tempest,
- nonetheless it is consumed by a number of plugins already. This class
- exists to provide some grace time for the move to tempest.lib.
- """
-
- def __init__(self, credentials, scope='project'):
- msg = ("tempest.manager.Manager is not a stable interface and as such "
- "it should not be imported directly. It will be removed as "
- "soon as the client manager becomes available in tempest.lib.")
- LOG.warning(msg)
- dscv = CONF.identity.disable_ssl_certificate_validation
- _, uri = tempest_clients.get_auth_provider_class(credentials)
- super(Manager, self).__init__(
- credentials=credentials, scope=scope,
- identity_uri=uri,
- disable_ssl_certificate_validation=dscv,
- ca_certs=CONF.identity.ca_certificates_file,
- trace_requests=CONF.debug.trace_requests)
-
-
-def get_auth_provider(credentials, pre_auth=False, scope='project'):
- """Shim to get_auth_provider in clients.py
-
- get_auth_provider used to be hosted in this module, but it has been
- moved to clients.py now as a more permanent location.
- This module will be removed eventually, and this shim is only
- maintained for the benefit of plugins already consuming this interface.
- """
- msg = ("tempest.manager.get_auth_provider is not a stable interface and "
- "as such it should not imported directly. It will be removed as "
- "the client manager becomes available in tempest.lib.")
- LOG.warning(msg)
- return tempest_clients.get_auth_provider(credentials=credentials,
- pre_auth=pre_auth, scope=scope)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 8866a22..4652af4 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -375,21 +375,35 @@
def create_backup(self, volume_id, name=None, description=None,
force=False, snapshot_id=None, incremental=False,
- container=None):
- """Creates backup
+ container=None, **kwargs):
+ """Creates a backup of the given volume_id or snapshot_id
- This wrapper utility creates backup and waits for backup to be
- in 'available' state.
+ This wrapper utility creates a backup and waits until it is in
+ 'available' state.
+
+ :param volume_id: UUID of the volume to back up
+ :param name: backup name, '$classname-backup' by default
+ :param description: Description of the backup, None by default
+ :param force: boolean whether to backup even if the volume is attached
+ False by default
+ :param snapshot_id: UUID of the source snapshot to back up
+ None by default
+ :param incremental: boolean, False by default
+ :param container: a container name, None by default
+ :param **kwargs: additional parameters per the documentation:
+ https://docs.openstack.org/api-ref/block-storage/v3/
+ #create-a-backup
"""
name = name or data_utils.rand_name(
self.__class__.__name__ + "-backup")
- kwargs = {'name': name,
- 'description': description,
- 'force': force,
- 'snapshot_id': snapshot_id,
- 'incremental': incremental,
- 'container': container}
+ args = {'name': name,
+ 'description': description,
+ 'force': force,
+ 'snapshot_id': snapshot_id,
+ 'incremental': incremental,
+ 'container': container}
+ args.update(kwargs)
backup = self.backups_client.create_backup(volume_id=volume_id,
**kwargs)['backup']
self.addCleanup(self.backups_client.delete_backup, backup['id'])
@@ -397,14 +411,20 @@
backup['id'], 'available')
return backup
- def restore_backup(self, backup_id):
- """Restore backup
+ def restore_backup(self, backup_id, **kwargs):
+ """Restores a backup given by the backup_id
- This wrapper utility restores backup and waits for backup to be
- in 'available' state.
+ This wrapper utility restores a backup and waits until it is in
+ 'available' state.
+
+ :param backup_id: UUID of a backup to restore
+ :param **kwargs: additional parameters per the documentation:
+ https://docs.openstack.org/api-ref/block-storage/v3/
+ #restore-a-backup
"""
- restore = self.backups_client.restore_backup(backup_id)['restore']
+ body = self.backups_client.restore_backup(backup_id, **kwargs)
+ restore = body['restore']
self.addCleanup(self.volumes_client.delete_volume,
restore['volume_id'])
waiters.wait_for_volume_resource_status(self.backups_client,
@@ -431,11 +451,20 @@
server_id, 'ACTIVE')
def create_volume_snapshot(self, volume_id, name=None, description=None,
- metadata=None, force=False):
- """Creates volume
+ metadata=None, force=False, **kwargs):
+ """Creates volume's snapshot
- This wrapper utility creates volume snapshot and waits for backup
- to be in 'available' state.
+ This wrapper utility creates volume snapshot and waits for it until
+ it is in 'available' state.
+
+ :param volume_id: UUID of a volume to create snapshot of
+ :param name: name of the snapshot, '$classname-snapshot' by default
+ :param description: description of the snapshot
+ :param metadata: metadata key and value pairs for the snapshot
+ :param force: whether snapshot even when the volume is attached
+ :param **kwargs: additional parameters per the doc
+ https://docs.openstack.org/api-ref/block-storage/v3/
+ #create-a-snapshot
"""
name = name or data_utils.rand_name(
@@ -445,7 +474,8 @@
force=force,
name=name,
description=description,
- metadata=metadata)['snapshot']
+ metadata=metadata,
+ **kwargs)['snapshot']
self.addCleanup(self.snapshots_client.wait_for_resource_deletion,
snapshot['id'])
@@ -515,7 +545,7 @@
self.addCleanup(self._cleanup_volume_type, volume_type)
return volume_type
- def _create_loginable_secgroup_rule(self, secgroup_id=None, rulesets=None):
+ def create_loginable_secgroup_rule(self, secgroup_id=None, rulesets=None):
"""Create loginable security group rule by compute clients.
This function will create by default the following rules:
@@ -575,7 +605,7 @@
secgroup['id'])
# Add rules to the security group
- self._create_loginable_secgroup_rule(secgroup['id'])
+ self.create_loginable_secgroup_rule(secgroup['id'])
return secgroup
def get_remote_client(self, ip_address, username=None, private_key=None,
@@ -1346,7 +1376,7 @@
project_id=project_id)
# Add rules to the security group
- rules = self._create_loginable_secgroup_rule(
+ rules = self.create_loginable_secgroup_rule(
security_group_rules_client=security_group_rules_client,
secgroup=secgroup,
security_groups_client=security_groups_client)
@@ -1387,10 +1417,10 @@
client.delete_security_group, secgroup['id'])
return secgroup
- def _create_security_group_rule(self, secgroup=None,
- sec_group_rules_client=None,
- project_id=None,
- security_groups_client=None, **kwargs):
+ def create_security_group_rule(self, secgroup=None,
+ sec_group_rules_client=None,
+ project_id=None,
+ security_groups_client=None, **kwargs):
"""Create a rule from a dictionary of rule parameters.
Create a rule in a secgroup. if secgroup not defined will search for
@@ -1435,9 +1465,9 @@
return sg_rule
- def _create_loginable_secgroup_rule(self, security_group_rules_client=None,
- secgroup=None,
- security_groups_client=None):
+ def create_loginable_secgroup_rule(self, security_group_rules_client=None,
+ secgroup=None,
+ security_groups_client=None):
"""Create loginable security group rule by neutron clients by default.
This function will create:
@@ -1474,7 +1504,7 @@
for r_direction in ['ingress', 'egress']:
ruleset['direction'] = r_direction
try:
- sg_rule = self._create_security_group_rule(
+ sg_rule = self.create_security_group_rule(
sec_group_rules_client=sec_group_rules_client,
secgroup=secgroup,
security_groups_client=security_groups_client,
@@ -1490,7 +1520,7 @@
return rules
- def _get_router(self, client=None, project_id=None):
+ def _get_router(self, client=None, project_id=None, **kwargs):
"""Retrieve a router for the given tenant id.
If a public router has been configured, it will be returned.
@@ -1510,11 +1540,20 @@
body = client.show_router(router_id)
return body['router']
elif network_id:
+ name = kwargs.pop('name', None)
+ if not name:
+ namestart = self.__class__.__name__ + '-router'
+ name = data_utils.rand_name(namestart)
+
+ ext_gw_info = kwargs.pop('external_gateway_info', None)
+ if not ext_gw_info:
+ ext_gw_info = dict(network_id=network_id)
router = client.create_router(
- name=data_utils.rand_name(self.__class__.__name__ + '-router'),
- admin_state_up=True,
+ name=name,
+ admin_state_up=kwargs.get('admin_state_up', True),
project_id=project_id,
- external_gateway_info=dict(network_id=network_id))['router']
+ external_gateway_info=ext_gw_info,
+ **kwargs)['router']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
client.delete_router, router['id'])
return router
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 03a4a39..496a371 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -217,7 +217,7 @@
direction='ingress',
)
sec_group_rules_client = tenant.manager.security_group_rules_client
- self._create_security_group_rule(
+ self.create_security_group_rule(
secgroup=access_sg,
sec_group_rules_client=sec_group_rules_client,
**ssh_rule)
@@ -385,7 +385,7 @@
remote_group_id=tenant.security_groups['default']['id'],
direction='ingress'
)
- self._create_security_group_rule(
+ self.create_security_group_rule(
secgroup=tenant.security_groups['default'],
security_groups_client=tenant.manager.security_groups_client,
**ruleset
@@ -413,7 +413,7 @@
protocol = ruleset['protocol']
sec_group_rules_client = (
dest_tenant.manager.security_group_rules_client)
- self._create_security_group_rule(
+ self.create_security_group_rule(
secgroup=dest_tenant.security_groups['default'],
sec_group_rules_client=sec_group_rules_client,
**ruleset
@@ -429,7 +429,7 @@
# allow reverse traffic and check
sec_group_rules_client = (
source_tenant.manager.security_group_rules_client)
- self._create_security_group_rule(
+ self.create_security_group_rule(
secgroup=source_tenant.security_groups['default'],
sec_group_rules_client=sec_group_rules_client,
**ruleset
@@ -543,7 +543,7 @@
direction='ingress',
)
sec_group_rules_client = new_tenant.manager.security_group_rules_client
- self._create_security_group_rule(
+ self.create_security_group_rule(
secgroup=new_sg,
sec_group_rules_client=sec_group_rules_client,
**icmp_rule)
@@ -596,7 +596,7 @@
protocol='icmp',
direction='ingress'
)
- self._create_security_group_rule(
+ self.create_security_group_rule(
secgroup=tenant.security_groups['default'],
**ruleset
)
diff --git a/tempest/test.py b/tempest/test.py
index f383bc1..68602d6 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -38,12 +38,6 @@
CONF = config.CONF
-# TODO(oomichi): This test.idempotent_id should be removed after all projects
-# switch to use decorators.idempotent_id.
-idempotent_id = debtcollector.moves.moved_function(
- decorators.idempotent_id, 'idempotent_id', __name__,
- version='Mitaka', removal_version='?')
-
attr = debtcollector.moves.moved_function(
decorators.attr, 'attr', __name__,
diff --git a/tempest/tests/lib/services/identity/v3/test_identity_providers_client.py b/tempest/tests/lib/services/identity/v3/test_identity_providers_client.py
new file mode 100644
index 0000000..964c51b
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_identity_providers_client.py
@@ -0,0 +1,142 @@
+# Copyright 2020 Samsung Electronics Co., Ltd
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from tempest.lib.services.identity.v3 import identity_providers_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestIdentityProvidersClient(base.BaseServiceTest):
+ FAKE_IDENTITY_PROVIDERS_INFO = {
+ "identity_providers": [
+ {
+ "domain_id": "FAKE_DOMAIN_ID",
+ "description": "FAKE IDENTITY PROVIDER",
+ "remote_ids": ["fake_id_1", "fake_id_2"],
+ "enabled": True,
+ "id": "FAKE_ID",
+ "links": {
+ "protocols": "http://example.com/identity/v3/" +
+ "OS-FEDERATION/identity_providers/" +
+ "FAKE_ID/protocols",
+ "self": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "identity_providers/FAKE_ID"
+ }
+ }
+ ],
+ "links": {
+ "next": None,
+ "previous": None,
+ "self": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "identity_providers"
+ }
+ }
+
+ FAKE_IDENTITY_PROVIDER_INFO = {
+ "identity_provider": {
+ "authorization_ttl": None,
+ "domain_id": "FAKE_DOMAIN_ID",
+ "description": "FAKE IDENTITY PROVIDER",
+ "remote_ids": ["fake_id_1", "fake_id_2"],
+ "enabled": True,
+ "id": "ACME",
+ "links": {
+ "protocols": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "identity_providers/FAKE_ID/protocols",
+ "self": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "identity_providers/FAKE_ID"
+ }
+ }
+ }
+
+ def setUp(self):
+ super(TestIdentityProvidersClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = identity_providers_client.IdentityProvidersClient(
+ fake_auth, 'identity', 'regionOne')
+
+ def _test_register_identity_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.register_identity_provider,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ self.FAKE_IDENTITY_PROVIDER_INFO,
+ bytes_body,
+ identity_provider_id="FAKE_ID",
+ status=201)
+
+ def _test_list_identity_providers(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_identity_providers,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_IDENTITY_PROVIDERS_INFO,
+ bytes_body,
+ status=200)
+
+ def _test_get_identity_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.get_identity_provider,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_IDENTITY_PROVIDER_INFO,
+ bytes_body,
+ identity_provider_id="FAKE_ID",
+ status=200)
+
+ def _test_delete_identity_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.delete_identity_provider,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ bytes_body,
+ identity_provider_id="FAKE_ID",
+ status=204)
+
+ def _test_update_identity_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_identity_provider,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_IDENTITY_PROVIDER_INFO,
+ bytes_body,
+ identity_provider_id="FAKE_ID",
+ status=200)
+
+ def test_register_identity_provider_with_str_body(self):
+ self._test_register_identity_provider()
+
+ def test_register_identity_provider_with_bytes_body(self):
+ self._test_register_identity_provider(bytes_body=True)
+
+ def test_list_identity_providers_with_str_body(self):
+ self._test_list_identity_providers()
+
+ def test_list_identity_providers_with_bytes_body(self):
+ self._test_list_identity_providers(bytes_body=True)
+
+ def test_get_identity_provider_with_str_body(self):
+ self._test_get_identity_provider()
+
+ def test_get_identity_provider_with_bytes_body(self):
+ self._test_get_identity_provider(bytes_body=True)
+
+ def test_delete_identity_provider_with_str_body(self):
+ self._test_delete_identity_provider()
+
+ def test_delete_identity_provider_with_bytes_body(self):
+ self._test_delete_identity_provider(bytes_body=True)
+
+ def test_update_identity_provider_with_str_body(self):
+ self._test_update_identity_provider()
+
+ def test_update_identity_provider_with_bytes_body(self):
+ self._test_update_identity_provider(bytes_body=True)
diff --git a/tempest/tests/lib/services/identity/v3/test_mappings_client.py b/tempest/tests/lib/services/identity/v3/test_mappings_client.py
new file mode 100644
index 0000000..845a3f9
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_mappings_client.py
@@ -0,0 +1,183 @@
+# Copyright 2020 Samsung Electronics Co., Ltd
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from tempest.lib.services.identity.v3 import mappings_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestMappingsClient(base.BaseServiceTest):
+ FAKE_MAPPING_INFO = {
+ "mapping": {
+ "id": "fake123",
+ "links": {
+ "self": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "mappings/fake123"
+ },
+ "rules": [
+ {
+ "local": [
+ {
+ "user": {
+ "name": "{0}"
+ }
+ },
+ {
+ "group": {
+ "id": "0cd5e9"
+ }
+ }
+ ],
+ "remote": [
+ {
+ "type": "UserName"
+ },
+ {
+ "type": "orgPersonType",
+ "not_any_of": [
+ "Contractor",
+ "Guest"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+
+ FAKE_MAPPINGS_INFO = {
+ "links": {
+ "next": None,
+ "previous": None,
+ "self": "http://example.com/identity/v3/OS-FEDERATION/mappings"
+ },
+ "mappings": [
+ {
+ "id": "fake123",
+ "links": {
+ "self": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "mappings/fake123"
+ },
+ "rules": [
+ {
+ "local": [
+ {
+ "user": {
+ "name": "{0}"
+ }
+ },
+ {
+ "group": {
+ "id": "0cd5e9"
+ }
+ }
+ ],
+ "remote": [
+ {
+ "type": "UserName"
+ },
+ {
+ "type": "orgPersonType",
+ "any_one_of": [
+ "Contractor",
+ "SubContractor"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+
+ def setUp(self):
+ super(TestMappingsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = mappings_client.MappingsClient(
+ fake_auth, 'identity', 'regionOne')
+
+ def _test_create_mapping(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_mapping,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ self.FAKE_MAPPING_INFO,
+ bytes_body,
+ mapping_id="fake123",
+ status=201)
+
+ def _test_get_mapping(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.get_mapping,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_MAPPING_INFO,
+ bytes_body,
+ mapping_id="fake123",
+ status=200)
+
+ def _test_update_mapping(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_mapping,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_MAPPING_INFO,
+ bytes_body,
+ mapping_id="fake123",
+ status=200)
+
+ def _test_list_mappings(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_mappings,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_MAPPINGS_INFO,
+ bytes_body,
+ status=200)
+
+ def _test_delete_mapping(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.delete_mapping,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ bytes_body,
+ mapping_id="fake123",
+ status=204)
+
+ def test_create_mapping_with_str_body(self):
+ self._test_create_mapping()
+
+ def test_create_mapping_with_bytes_body(self):
+ self._test_create_mapping(bytes_body=True)
+
+ def test_get_mapping_with_str_body(self):
+ self._test_get_mapping()
+
+ def test_get_mapping_with_bytes_body(self):
+ self._test_get_mapping(bytes_body=True)
+
+ def test_update_mapping_with_str_body(self):
+ self._test_update_mapping()
+
+ def test_update_mapping_with_bytes_body(self):
+ self._test_update_mapping(bytes_body=True)
+
+ def test_list_mappings_with_str_body(self):
+ self._test_list_mappings()
+
+ def test_list_mappings_with_bytes_body(self):
+ self._test_list_mappings(bytes_body=True)
+
+ def test_delete_mapping_with_str_body(self):
+ self._test_delete_mapping()
+
+ def test_delete_mapping_with_bytes_body(self):
+ self._test_delete_mapping(bytes_body=True)
diff --git a/tempest/tests/lib/services/identity/v3/test_protocols_client.py b/tempest/tests/lib/services/identity/v3/test_protocols_client.py
new file mode 100644
index 0000000..c1d04f4
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_protocols_client.py
@@ -0,0 +1,140 @@
+# Copyright 2020 Samsung Electronics Co., Ltd
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from tempest.lib.services.identity.v3 import protocols_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestProtocolsClient(base.BaseServiceTest):
+ FAKE_PROTOCOLS_INFO = {
+ "links": {
+ "next": None,
+ "previous": None,
+ "self": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "identity_providers/FAKE_ID/protocols"
+ },
+ "protocols": [
+ {
+ "id": "fake_id1",
+ "links": {
+ "identity_provider": "http://example.com/identity/v3/" +
+ "OS-FEDERATION/identity_providers/" +
+ "FAKE_ID",
+ "self": "http://example.com/identity/v3/OS-FEDERATION/"
+ "identity_providers/FAKE_ID/protocols/fake_id1"
+ },
+ "mapping_id": "fake123"
+ }
+ ]
+ }
+
+ FAKE_PROTOCOL_INFO = {
+ "protocol": {
+ "id": "fake_id1",
+ "links": {
+ "identity_provider": "http://example.com/identity/v3/OS-" +
+ "FEDERATION/identity_providers/FAKE_ID",
+ "self": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "identity_providers/FAKE_ID/protocols/fake_id1"
+ },
+ "mapping_id": "fake123"
+ }
+ }
+
+ def setUp(self):
+ super(TestProtocolsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = protocols_client.ProtocolsClient(
+ fake_auth, 'identity', 'regionOne')
+
+ def _test_add_protocol_to_identity_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.add_protocol_to_identity_provider,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ self.FAKE_PROTOCOL_INFO,
+ bytes_body,
+ idp_id="FAKE_ID",
+ protocol_id="fake_id1",
+ status=201)
+
+ def _test_list_protocols_of_identity_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_protocols_of_identity_provider,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_PROTOCOLS_INFO,
+ bytes_body,
+ idp_id="FAKE_ID",
+ status=200)
+
+ def _test_get_protocol_for_identity_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.get_protocol_for_identity_provider,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_PROTOCOL_INFO,
+ bytes_body,
+ idp_id="FAKE_ID",
+ protocol_id="fake_id1",
+ status=200)
+
+ def _test_update_mapping_for_identity_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_mapping_for_identity_provider,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_PROTOCOL_INFO,
+ bytes_body,
+ idp_id="FAKE_ID",
+ protocol_id="fake_id1",
+ status=200)
+
+ def _test_delete_protocol_from_identity_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.delete_protocol_from_identity_provider,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ bytes_body,
+ idp_id="FAKE_ID",
+ protocol_id="fake_id1",
+ status=204)
+
+ def test_add_protocol_to_identity_provider_with_str_body(self):
+ self._test_add_protocol_to_identity_provider()
+
+ def test_add_protocol_to_identity_provider_with_bytes_body(self):
+ self._test_add_protocol_to_identity_provider(bytes_body=True)
+
+ def test_list_protocols_of_identity_provider_with_str_body(self):
+ self._test_list_protocols_of_identity_provider()
+
+ def test_list_protocols_of_identity_provider_with_bytes_body(self):
+ self._test_list_protocols_of_identity_provider(bytes_body=True)
+
+ def test_get_protocol_for_identity_provider_with_str_body(self):
+ self._test_get_protocol_for_identity_provider()
+
+ def test_get_protocol_for_identity_provider_with_bytes_body(self):
+ self._test_get_protocol_for_identity_provider(bytes_body=True)
+
+ def test_update_mapping_for_identity_provider_with_str_body(self):
+ self._test_update_mapping_for_identity_provider()
+
+ def test_update_mapping_for_identity_provider_with_bytes_body(self):
+ self._test_update_mapping_for_identity_provider(bytes_body=True)
+
+ def test_delete_protocol_from_identity_provider_with_str_body(self):
+ self._test_delete_protocol_from_identity_provider()
+
+ def test_delete_protocol_from_identity_provider_with_bytes_body(self):
+ self._test_delete_protocol_from_identity_provider(bytes_body=False)
diff --git a/tempest/tests/lib/services/identity/v3/test_service_providers_client.py b/tempest/tests/lib/services/identity/v3/test_service_providers_client.py
new file mode 100644
index 0000000..ec908bc
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_service_providers_client.py
@@ -0,0 +1,157 @@
+# Copyright 2020 Samsung Electronics Co., Ltd
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from tempest.lib.services.identity.v3 import service_providers_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestServiceProvidersClient(base.BaseServiceTest):
+ FAKE_SERVICE_PROVIDER_INFO = {
+ "service_provider": {
+ "auth_url": "https://example.com/identity/v3/OS-FEDERATION/" +
+ "identity_providers/FAKE_ID/protocols/fake_id1/auth",
+ "description": "Fake Service Provider",
+ "enabled": True,
+ "id": "FAKE_ID",
+ "links": {
+ "self": "https://example.com/identity/v3/OS-FEDERATION/" +
+ "service_providers/FAKE_ID"
+ },
+ "relay_state_prefix": "ss:mem:",
+ "sp_url": "https://example.com/identity/Shibboleth.sso/" +
+ "FAKE_ID1/ECP"
+ }
+ }
+
+ FAKE_SERVICE_PROVIDERS_INFO = {
+ "links": {
+ "next": None,
+ "previous": None,
+ "self": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "service_providers"
+ },
+ "service_providers": [
+ {
+ "auth_url": "https://example.com/identity/v3/OS-FEDERATION/" +
+ "identity_providers/acme/protocols/saml2/auth",
+ "description": "Stores ACME identities",
+ "enabled": True,
+ "id": "ACME",
+ "links": {
+ "self": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "service_providers/ACME"
+ },
+ "relay_state_prefix": "ss:mem:",
+ "sp_url": "https://example.com/identity/Shibboleth.sso/" +
+ "SAML2/ECP"
+ },
+ {
+ "auth_url": "https://other.example.com/identity/v3/" +
+ "OS-FEDERATION/identity_providers/acme/" +
+ "protocols/saml2/auth",
+ "description": "Stores contractor identities",
+ "enabled": False,
+ "id": "ACME-contractors",
+ "links": {
+ "self": "http://example.com/identity/v3/OS-FEDERATION/" +
+ "service_providers/ACME-contractors"
+ },
+ "relay_state_prefix": "ss:mem:",
+ "sp_url": "https://other.example.com/identity/Shibboleth" +
+ ".sso/SAML2/ECP"
+ }
+ ]
+ }
+
+ def setUp(self):
+ super(TestServiceProvidersClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = service_providers_client.ServiceProvidersClient(
+ fake_auth, 'identity', 'regionOne')
+
+ def _test_register_service_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.register_service_provider,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ self.FAKE_SERVICE_PROVIDER_INFO,
+ bytes_body,
+ service_provider_id="FAKE_ID",
+ status=201)
+
+ def _test_list_service_providers(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_service_providers,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_SERVICE_PROVIDERS_INFO,
+ bytes_body,
+ status=200)
+
+ def _test_get_service_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.get_service_provider,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_SERVICE_PROVIDER_INFO,
+ bytes_body,
+ service_provider_id="FAKE_ID",
+ status=200)
+
+ def _test_delete_service_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.delete_service_provider,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ bytes_body,
+ service_provider_id="FAKE_ID",
+ status=204)
+
+ def _test_update_service_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_service_provider,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_SERVICE_PROVIDER_INFO,
+ bytes_body,
+ service_provider_id="FAKE_ID",
+ status=200)
+
+ def test_register_service_provider_with_str_body(self):
+ self._test_register_service_provider()
+
+ def test_register_service_provider_with_bytes_body(self):
+ self._test_register_service_provider(bytes_body=True)
+
+ def test_list_service_providers_with_str_body(self):
+ self._test_list_service_providers()
+
+ def test_list_service_providers_with_bytes_body(self):
+ self._test_list_service_providers(bytes_body=True)
+
+ def test_get_service_provider_with_str_body(self):
+ self._test_get_service_provider()
+
+ def test_get_service_provider_with_bytes_body(self):
+ self._test_get_service_provider(bytes_body=True)
+
+ def test_delete_service_provider_with_str_body(self):
+ self._test_delete_service_provider()
+
+ def test_delete_service_provider_with_bytes_body(self):
+ self._test_delete_service_provider(bytes_body=True)
+
+ def test_update_service_provider_with_str_body(self):
+ self._test_update_service_provider()
+
+ def test_update_service_provider_with_bytes_body(self):
+ self._test_update_service_provider(bytes_body=True)
diff --git a/tempest/tests/lib/services/identity/v3/test_trusts_client.py b/tempest/tests/lib/services/identity/v3/test_trusts_client.py
index a1ca020..33dca7d 100644
--- a/tempest/tests/lib/services/identity/v3/test_trusts_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_trusts_client.py
@@ -94,6 +94,35 @@
}
}
+ FAKE_LIST_TRUSTS_ROLES = {
+ "roles": [
+ {
+ "id": "c1648e",
+ "links": {
+ "self": "http://example.com/identity/v3/roles/c1648e"
+ },
+ "name": "manager"
+ },
+ {
+ "id": "ed7b78",
+ "links": {
+ "self": "http://example.com/identity/v3/roles/ed7b78"
+ },
+ "name": "member"
+ }
+ ]
+ }
+
+ FAKE_TRUST_ROLE = {
+ "role": {
+ "id": "c1648e",
+ "links": {
+ "self": "http://example.com/identity/v3/roles/c1648e"
+ },
+ "name": "manager"
+ }
+ }
+
def setUp(self):
super(TestTrustsClient, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -123,6 +152,43 @@
self.FAKE_LIST_TRUSTS,
bytes_body)
+ def _test_list_trust_roles(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_trust_roles,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_TRUSTS_ROLES,
+ bytes_body,
+ trust_id="1ff900")
+
+ def test_check_trust_role(self):
+ self.check_service_client_function(
+ self.client.check_trust_role,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ trust_id="1ff900",
+ role_id="ed7b78")
+
+ def _check_show_trust_role(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_trust_role,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_TRUST_ROLE,
+ bytes_body,
+ trust_id="1ff900",
+ role_id="ed7b78")
+
+ def test_list_trust_roles_with_str_body(self):
+ self._test_list_trust_roles()
+
+ def test_list_trust_roles_with_bytes_body(self):
+ self._test_list_trust_roles(bytes_body=True)
+
+ def test_check_show_trust_role_with_str_body(self):
+ self._check_show_trust_role()
+
+ def test_check_show_trust_role_with_bytes_body(self):
+ self._check_show_trust_role(bytes_body=True)
+
def test_create_trust_with_str_body(self):
self._test_create_trust()
diff --git a/tempest/tests/lib/services/network/test_ports_client.py b/tempest/tests/lib/services/network/test_ports_client.py
index 20ef3f1..9ca9ac6 100644
--- a/tempest/tests/lib/services/network/test_ports_client.py
+++ b/tempest/tests/lib/services/network/test_ports_client.py
@@ -22,53 +22,126 @@
class TestPortsClient(base.BaseServiceTest):
+ FAKE_CREATE_PORTS = {
+ "port": {
+ "binding:host_id": "4df8d9ff-6f6f-438f-90a1-ef660d4586ad",
+ "binding:profile": {
+ "local_link_information": [
+ {
+ "port_id": "Ethernet3/1",
+ "switch_id": "0a:1b:2c:3d:4e:5f",
+ "switch_info": "switch1"
+ }
+ ]
+ },
+ "binding:vnic_type": "baremetal",
+ "device_id": "d90a13da-be41-461f-9f99-1dbcf438fdf2",
+ "device_owner": "baremetal:none",
+ "dns_domain": "my-domain.org.",
+ "dns_name": "myport",
+ "qos_policy_id": "29d5e02e-d5ab-4929-bee4-4a9fc12e22ae",
+ "uplink_status_propagation": False
+ }
+ }
+
FAKE_PORTS = {
"ports": [
{
"admin_state_up": True,
"allowed_address_pairs": [],
+ "created_at": "2016-03-08T20:19:41",
"data_plane_status": None,
"description": "",
"device_id": "9ae135f4-b6e0-4dad-9e91-3c223e385824",
"device_owner": "network:router_gateway",
- "extra_dhcp_opts": [],
+ "dns_assignment": [
+ {
+ "hostname": "myport",
+ "ip_address": "172.24.4.2",
+ "fqdn": "myport.my-domain.org"
+ }
+ ],
+ "dns_domain": "my-domain.org.",
+ "dns_name": "myport",
+ "extra_dhcp_opts": [
+ {
+ "opt_value": "pxelinux.0",
+ "ip_version": 4,
+ "opt_name": "bootfile-name"
+ }
+ ],
"fixed_ips": [
{
"ip_address": "172.24.4.2",
- "subnet_id": "008ba151-0b8c-4a67-98b5-0d2b87666062"
+ "subnet_id":
+ "008ba151-0b8c-4a67-98b5-0d2b87666062"
}
],
"id": "d80b1a3b-4fc1-49f3-952e-1e2ab7081d8b",
+ "ip_allocation": "immediate",
"mac_address": "fa:16:3e:58:42:ed",
"name": "",
"network_id": "70c1db1f-b701-45bd-96e0-a313ee3430b3",
"project_id": "",
+ "revision_number": 1,
"security_groups": [],
"status": "ACTIVE",
- "tenant_id": ""
+ "tags": ["tag1,tag2"],
+ "tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa",
+ "updated_at": "2016-03-08T20:19:41",
+ "qos_network_policy_id":
+ "174dd0c1-a4eb-49d4-a807-ae80246d82f4",
+ "qos_policy_id": "29d5e02e-d5ab-4929-bee4-4a9fc12e22ae",
+ "port_security_enabled": False,
+ "uplink_status_propagation": False
},
{
"admin_state_up": True,
"allowed_address_pairs": [],
+ "created_at": "2016-03-08T20:19:41",
"data_plane_status": None,
"description": "",
"device_id": "9ae135f4-b6e0-4dad-9e91-3c223e385824",
"device_owner": "network:router_interface",
- "extra_dhcp_opts": [],
+ "dns_assignment": [
+ {
+ "hostname": "myport2",
+ "ip_address": "10.0.0.1",
+ "fqdn": "myport2.my-domain.org"
+ }
+ ],
+ "dns_domain": "my-domain.org.",
+ "dns_name": "myport2",
+ "extra_dhcp_opts": [
+ {
+ "opt_value": "pxelinux.0",
+ "ip_version": 4,
+ "opt_name": "bootfile-name"
+ }
+ ],
"fixed_ips": [
{
"ip_address": "10.0.0.1",
- "subnet_id": "288bf4a1-51ba-43b6-9d0a-520e9005db17"
+ "subnet_id":
+ "288bf4a1-51ba-43b6-9d0a-520e9005db17"
}
],
"id": "f71a6703-d6de-4be1-a91a-a570ede1d159",
+ "ip_allocation": "immediate",
"mac_address": "fa:16:3e:bb:3c:e4",
"name": "",
"network_id": "f27aa545-cbdd-4907-b0c6-c9e8b039dcc2",
"project_id": "d397de8a63f341818f198abb0966f6f3",
+ "revision_number": 1,
"security_groups": [],
"status": "ACTIVE",
- "tenant_id": "d397de8a63f341818f198abb0966f6f3"
+ "tags": ["tag1,tag2"],
+ "tenant_id": "d397de8a63f341818f198abb0966f6f3",
+ "updated_at": "2016-03-08T20:19:41",
+ "qos_network_policy_id": None,
+ "qos_policy_id": None,
+ "port_security_enabled": False,
+ "uplink_status_propagation": False
}
]
}
@@ -112,7 +185,7 @@
self.check_service_client_function(
self.ports_client.create_port,
"tempest.lib.common.rest_client.RestClient.post",
- {"port": self.FAKE_PORTS["ports"][0]},
+ self.FAKE_CREATE_PORTS,
bytes_body,
201,
**self.FAKE_PORT1)
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index 6018441..1889420 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -19,7 +19,6 @@
from tempest.common import utils
from tempest import config
from tempest import exceptions
-from tempest.lib.common.utils import data_utils
from tempest import test
from tempest.tests import base
from tempest.tests import fake_config
@@ -33,47 +32,6 @@
fake_config.FakePrivate)
-# NOTE: The test module is for tempest.test.idempotent_id.
-# After all projects switch to use decorators.idempotent_id,
-# we can remove tempest.test.idempotent_id as well as this
-# test module
-class TestIdempotentIdDecorator(BaseDecoratorsTest):
-
- def _test_helper(self, _id, **decorator_args):
- @test.idempotent_id(_id)
- def foo():
- """Docstring"""
- pass
-
- return foo
-
- def _test_helper_without_doc(self, _id, **decorator_args):
- @test.idempotent_id(_id)
- def foo():
- pass
-
- return foo
-
- def test_positive(self):
- _id = data_utils.rand_uuid()
- foo = self._test_helper(_id)
- self.assertIn('id-%s' % _id, getattr(foo, '__testtools_attrs'))
- self.assertTrue(foo.__doc__.startswith('Test idempotent id: %s' % _id))
-
- def test_positive_without_doc(self):
- _id = data_utils.rand_uuid()
- foo = self._test_helper_without_doc(_id)
- self.assertTrue(foo.__doc__.startswith('Test idempotent id: %s' % _id))
-
- def test_idempotent_id_not_str(self):
- _id = 42
- self.assertRaises(TypeError, self._test_helper, _id)
-
- def test_idempotent_id_not_valid_uuid(self):
- _id = '42'
- self.assertRaises(ValueError, self._test_helper, _id)
-
-
class TestServicesDecorator(BaseDecoratorsTest):
def _test_services_helper(self, *decorator_args):
class TestFoo(test.BaseTestCase):
diff --git a/tools/generate-tempest-plugins-list.py b/tools/generate-tempest-plugins-list.py
index 415ad05..1b5b369 100644
--- a/tools/generate-tempest-plugins-list.py
+++ b/tools/generate-tempest-plugins-list.py
@@ -54,6 +54,9 @@
'x/kingbird', # https://bugs.launchpad.net/kingbird/+bug/1869722
# vmware-nsx is excluded since https://review.opendev.org/#/c/736952
'x/vmware-nsx-tempest-plugin',
+ # mogan is unmaintained now, remove from the list when this is merged:
+ # https://review.opendev.org/c/x/mogan/+/767718
+ 'x/mogan',
]
url = 'https://review.opendev.org/projects/'
diff --git a/tools/tempest-integrated-gate-compute-exclude-list.txt b/tools/tempest-integrated-gate-compute-exclude-list.txt
index 2290751..8805262 100644
--- a/tools/tempest-integrated-gate-compute-exclude-list.txt
+++ b/tools/tempest-integrated-gate-compute-exclude-list.txt
@@ -11,9 +11,3 @@
tempest.scenario.test_object_storage_basic_ops.TestObjectStorageBasicOps.test_swift_basic_ops
tempest.scenario.test_object_storage_basic_ops.TestObjectStorageBasicOps.test_swift_acl_anonymous_download
tempest.scenario.test_volume_backup_restore.TestVolumeBackupRestore.test_volume_backup_restore
-
-# Skip test scenario when creating second image from instance
-# https://bugs.launchpad.net/tripleo/+bug/1881592
-# The test is most likely wrong and may fail if the fists image is create quickly.
-# FIXME: Either fix the test so it won't race or consider if we should cover the scenario at all.
-tempest.api.compute.images.test_images_oneserver_negative.ImagesOneServerNegativeTestJSON.test_create_second_image_when_first_image_is_being_saved
diff --git a/tox.ini b/tox.ini
index c01852b..2315163 100644
--- a/tox.ini
+++ b/tox.ini
@@ -136,7 +136,7 @@
commands =
find . -type f -name "*.pyc" -delete
tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.api)' --exclude-list ./tools/tempest-integrated-gate-networking-exclude-list.txt {posargs}
- tempest run --combine --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)' --exlude-list ./tools/tempest-integrated-gate-networking-exclude-list.txt {posargs}
+ tempest run --combine --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)' --exclude-list ./tools/tempest-integrated-gate-networking-exclude-list.txt {posargs}
[testenv:integrated-compute]
envdir = .tox/tempest
diff --git a/zuul.d/integrated-gate.yaml b/zuul.d/integrated-gate.yaml
index 9684015..52ccd3e 100644
--- a/zuul.d/integrated-gate.yaml
+++ b/zuul.d/integrated-gate.yaml
@@ -11,8 +11,10 @@
vars:
tox_envlist: all
tempest_test_regex: tempest
- devstack_localrc:
- ENABLE_FILE_INJECTION: true
+ # TODO(gmann): Enable File injection tests once nova bug is fixed
+ # https://bugs.launchpad.net/nova/+bug/1882421
+ # devstack_localrc:
+ # ENABLE_FILE_INJECTION: true
- job:
name: tempest-ipv6-only
@@ -394,7 +396,9 @@
Former name for this job was legacy-tempest-dsvm-neutron-pg-full.
vars:
devstack_localrc:
- ENABLE_FILE_INJECTION: true
+ # TODO(gmann): Enable File injection tests once nova bug is fixed
+ # https://bugs.launchpad.net/nova/+bug/1882421
+ # ENABLE_FILE_INJECTION: true
DATABASE_TYPE: postgresql
- project-template: