Merge "Add placement API methods for testing routed provider nets"
diff --git a/releasenotes/notes/new-placement-client-methods-e35c473e29494928.yaml b/releasenotes/notes/new-placement-client-methods-e35c473e29494928.yaml
new file mode 100644
index 0000000..9e6d49a
--- /dev/null
+++ b/releasenotes/notes/new-placement-client-methods-e35c473e29494928.yaml
@@ -0,0 +1,11 @@
+---
+features:
+ - |
+ Add ``placement`` API methods for testing Routed Provider Networks feature.
+ The following API calls are available for tempest from now in the new
+ resource_providers_client:
+
+ * GET /resource_providers
+ * GET /resource_providers/{uuid}
+ * GET /resource_providers/{uuid}/inventories
+ * GET /resource_providers/{uuid}/aggregates
diff --git a/tempest/clients.py b/tempest/clients.py
index 8363a8d..6d19a0c 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -44,7 +44,7 @@
self._set_object_storage_clients()
self._set_image_clients()
self._set_network_clients()
- self.placement_client = self.placement.PlacementClient()
+ self._set_placement_clients()
# TODO(andreaf) This is maintained for backward compatibility
# with plugins, but it should removed eventually, since it was
# never a stable interface and it's not useful anyways
@@ -139,6 +139,11 @@
self.snapshots_extensions_client = self.compute.SnapshotsClient(
**params_volume)
+ def _set_placement_clients(self):
+ self.placement_client = self.placement.PlacementClient()
+ self.resource_providers_client = \
+ self.placement.ResourceProvidersClient()
+
def _set_identity_clients(self):
# Clients below use the admin endpoint type of Keystone API v2
params_v2_admin = {
diff --git a/tempest/lib/services/placement/__init__.py b/tempest/lib/services/placement/__init__.py
index 5c20c57..daeaeab 100644
--- a/tempest/lib/services/placement/__init__.py
+++ b/tempest/lib/services/placement/__init__.py
@@ -14,5 +14,7 @@
from tempest.lib.services.placement.placement_client import \
PlacementClient
+from tempest.lib.services.placement.resource_providers_client import \
+ ResourceProvidersClient
-__all__ = ['PlacementClient']
+__all__ = ['PlacementClient', 'ResourceProvidersClient']
diff --git a/tempest/lib/services/placement/resource_providers_client.py b/tempest/lib/services/placement/resource_providers_client.py
new file mode 100644
index 0000000..56f6409
--- /dev/null
+++ b/tempest/lib/services/placement/resource_providers_client.py
@@ -0,0 +1,82 @@
+# 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
+from tempest.lib.services.placement import base_placement_client
+
+
+class ResourceProvidersClient(base_placement_client.BasePlacementClient):
+ """Client class for resource provider related methods
+
+ This client class aims to support read-only API operations for resource
+ providers. The following resources are supported:
+ * resource providers
+ * resource provider inventories
+ * resource provider aggregates
+ """
+
+ def list_resource_providers(self, **params):
+ """List resource providers.
+
+ For full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/placement/#list-resource-providers
+ """
+ url = '/resource_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 show_resource_provider(self, rp_uuid):
+ """Show resource provider.
+
+ For full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/placement/#show-resource-provider
+ """
+ url = '/resource_providers/%s' % rp_uuid
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_resource_provider_inventories(self, rp_uuid):
+ """List resource provider inventories.
+
+ For full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/placement/#list-resource-provider-inventories
+ """
+ url = '/resource_providers/%s/inventories' % rp_uuid
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_resource_provider_aggregates(self, rp_uuid):
+ """List resource provider aggregates.
+
+ For full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/placement/#list-resource-provider-aggregates
+ """
+ url = '/resource_providers/%s/aggregates' % rp_uuid
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/tests/lib/services/placement/test_resource_providers_client.py b/tempest/tests/lib/services/placement/test_resource_providers_client.py
new file mode 100644
index 0000000..11aeaf2
--- /dev/null
+++ b/tempest/tests/lib/services/placement/test_resource_providers_client.py
@@ -0,0 +1,119 @@
+# 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.placement import resource_providers_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestResourceProvidersClient(base.BaseServiceTest):
+ FAKE_RESOURCE_PROVIDER_UUID = '3722a86e-a563-11e9-9abb-c3d41b6d3abf'
+ FAKE_ROOT_PROVIDER_UUID = '4a6a57c8-a563-11e9-914e-f3e0478fce53'
+ FAKE_RESOURCE_PROVIDER = {
+ 'generation': 0,
+ 'name': 'Ceph Storage Pool',
+ 'uuid': FAKE_RESOURCE_PROVIDER_UUID,
+ 'parent_provider_uuid': FAKE_ROOT_PROVIDER_UUID,
+ 'root_provider_uuid': FAKE_ROOT_PROVIDER_UUID
+ }
+
+ FAKE_RESOURCE_PROVIDERS = {
+ 'resource_providers': [FAKE_RESOURCE_PROVIDER]
+ }
+
+ FAKE_RESOURCE_PROVIDER_INVENTORIES = {
+ 'inventories': {
+ 'DISK_GB': {
+ 'allocation_ratio': 1.0,
+ 'max_unit': 35,
+ 'min_unit': 1,
+ 'reserved': 0,
+ 'step_size': 1,
+ 'total': 35
+ }
+ },
+ 'resource_provider_generation': 7
+ }
+
+ FAKE_AGGREGATE_UUID = '1166be40-a567-11e9-9f2a-53827f9311fa'
+ FAKE_RESOURCE_PROVIDER_AGGREGATES = {
+ 'aggregates': [FAKE_AGGREGATE_UUID]
+ }
+
+ def setUp(self):
+ super(TestResourceProvidersClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = resource_providers_client.ResourceProvidersClient(
+ fake_auth, 'placement', 'regionOne')
+
+ def _test_list_resource_providers(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_resource_providers,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_RESOURCE_PROVIDERS,
+ to_utf=bytes_body,
+ status=200
+ )
+
+ def test_list_resource_providers_with_bytes_body(self):
+ self._test_list_resource_providers()
+
+ def test_list_resource_providers_with_str_body(self):
+ self._test_list_resource_providers(bytes_body=True)
+
+ def _test_show_resource_provider(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_resource_provider,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_RESOURCE_PROVIDER,
+ to_utf=bytes_body,
+ status=200,
+ rp_uuid=self.FAKE_RESOURCE_PROVIDER_UUID
+ )
+
+ def test_show_resource_provider_with_str_body(self):
+ self._test_show_resource_provider()
+
+ def test_show_resource_provider_with_bytes_body(self):
+ self._test_show_resource_provider(bytes_body=True)
+
+ def _test_list_resource_provider_inventories(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_resource_provider_inventories,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_RESOURCE_PROVIDER_INVENTORIES,
+ to_utf=bytes_body,
+ status=200,
+ rp_uuid=self.FAKE_RESOURCE_PROVIDER_UUID
+ )
+
+ def test_list_resource_provider_inventories_with_str_body(self):
+ self._test_list_resource_provider_inventories()
+
+ def test_list_resource_provider_inventories_with_bytes_body(self):
+ self._test_list_resource_provider_inventories(bytes_body=True)
+
+ def _test_list_resource_provider_aggregates(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_resource_provider_aggregates,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_RESOURCE_PROVIDER_AGGREGATES,
+ to_utf=bytes_body,
+ status=200,
+ rp_uuid=self.FAKE_RESOURCE_PROVIDER_UUID
+ )
+
+ def test_list_resource_provider_aggregates_with_str_body(self):
+ self._test_list_resource_provider_aggregates()
+
+ def test_list_resource_provider_aggregates_with_bytes_body(self):
+ self._test_list_resource_provider_aggregates(bytes_body=True)