Merge "Set PYTHON env variable for python3"
diff --git a/releasenotes/notes/add-image-clients-tests-49dbc0a0a4281a77.yaml b/releasenotes/notes/add-image-clients-tests-49dbc0a0a4281a77.yaml
new file mode 100644
index 0000000..9d1a003
--- /dev/null
+++ b/releasenotes/notes/add-image-clients-tests-49dbc0a0a4281a77.yaml
@@ -0,0 +1,9 @@
+---
+features:
+ - |
+ As in the [doc]:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html,
+ there are some apis are not included, add them.
+
+ * namespace_objects_client(v2)
+
diff --git a/releasenotes/notes/deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml b/releasenotes/notes/deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml
new file mode 100644
index 0000000..c0a06d1
--- /dev/null
+++ b/releasenotes/notes/deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+ - The default value for the ``reseller`` option in the
+ ``identity-feature-enabled`` section has been changed from ``False``
+ to ``True``.
+deprecations:
+ - The ``reseller`` option in the ``identity-feature-enabled`` section is now
+ deprecated.
diff --git a/releasenotes/notes/deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml b/releasenotes/notes/deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml
new file mode 100644
index 0000000..c80f159
--- /dev/null
+++ b/releasenotes/notes/deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+ - The default value for the ``volume_services`` option in the
+ ``volume_feature_enabled`` section has been changed from ``False``
+ to ``True``.
+deprecations:
+ - The ``volume_services`` option in the ``volume_feature_enabled`` section
+ is now deprecated.
diff --git a/tempest/api/compute/admin/test_auto_allocate_network.py b/tempest/api/compute/admin/test_auto_allocate_network.py
index 8e481fd..08e4072 100644
--- a/tempest/api/compute/admin/test_auto_allocate_network.py
+++ b/tempest/api/compute/admin/test_auto_allocate_network.py
@@ -17,7 +17,6 @@
from tempest.api.compute import base
from tempest.common import compute
from tempest.common import credentials_factory as credentials
-from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import test_utils
from tempest.lib import exceptions as lib_excs
@@ -152,9 +151,7 @@
# create the server with no networking
server, _ = compute.create_test_server(
self.os, networks='none', wait_until='ACTIVE')
- self.addCleanup(waiters.wait_for_server_termination,
- self.servers_client, server['id'])
- self.addCleanup(self.servers_client.delete_server, server['id'])
+ self.addCleanup(self.delete_server, server['id'])
# get the server ips
addresses = self.servers_client.list_addresses(
server['id'])['addresses']
@@ -182,9 +179,7 @@
min_count=3)
server_nets = set()
for server in servers:
- self.addCleanup(waiters.wait_for_server_termination,
- self.servers_client, server['id'])
- self.addCleanup(self.servers_client.delete_server, server['id'])
+ self.addCleanup(self.delete_server, server['id'])
# get the server ips
addresses = self.servers_client.list_addresses(
server['id'])['addresses']
diff --git a/tempest/api/compute/admin/test_volumes_negative.py b/tempest/api/compute/admin/test_volumes_negative.py
index b9dac6f..26b8742 100644
--- a/tempest/api/compute/admin/test_volumes_negative.py
+++ b/tempest/api/compute/admin/test_volumes_negative.py
@@ -49,6 +49,7 @@
self.server['id'], nonexistent_volume,
volumeId=volume['id'])
+ @test.related_bug('1629110', status_code=400)
@test.idempotent_id('7dcac15a-b107-46d3-a5f6-cb863f4e454a')
def test_update_attached_volume_with_nonexistent_volume_in_body(self):
volume = self.create_volume()
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index 38c294b..60caa19 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -43,7 +43,6 @@
group = {}
ip_range = {}
cls.expected = {
- 'id': None,
'parent_group_id': None,
'ip_protocol': cls.ip_protocol,
'from_port': from_port,
@@ -54,8 +53,6 @@
def _check_expected_response(self, actual_rule):
for key in self.expected:
- if key == 'id':
- continue
self.assertEqual(self.expected[key], actual_rule[key],
"Miss-matched key is %s" % key)
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index a21ce94..1731bf3 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -268,9 +268,7 @@
self.os, tenant_network=network, wait_until='ACTIVE', min_count=2)
# add our cleanups for the servers since we bypassed the base class
for server in servers:
- self.addCleanup(waiters.wait_for_server_termination,
- self.servers_client, server['id'])
- self.addCleanup(self.servers_client.delete_server, server['id'])
+ self.addCleanup(self.delete_server, server['id'])
for server in servers:
# attach the port to the server
diff --git a/tempest/api/compute/servers/test_device_tagging.py b/tempest/api/compute/servers/test_device_tagging.py
index b2d5ae7..1d502be 100644
--- a/tempest/api/compute/servers/test_device_tagging.py
+++ b/tempest/api/compute/servers/test_device_tagging.py
@@ -19,7 +19,6 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest.common.utils.linux import remote_client
-from tempest.common import waiters
from tempest import config
from tempest.lib import exceptions
from tempest import test
@@ -196,9 +195,7 @@
}
])
- self.addCleanup(waiters.wait_for_server_termination,
- self.servers_client, server['id'])
- self.addCleanup(self.servers_client.delete_server, server['id'])
+ self.addCleanup(self.delete_server, server['id'])
self.ssh_client = remote_client.RemoteClient(
self.get_server_ip(server),
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 1b1b339..f66bc72 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -217,6 +217,26 @@
name=server_name)
@test.attr(type=['negative'])
+ @test.related_bug('1651064', status_code=500)
+ @test.idempotent_id('12146ac1-d7df-4928-ad25-b1f99e5286cd')
+ def test_create_server_invalid_bdm_in_2nd_dict(self):
+ volume = self.create_volume()
+ bdm_1st = {"source_type": "image",
+ "delete_on_termination": True,
+ "boot_index": 0,
+ "uuid": self.image_ref,
+ "destination_type": "local"}
+ bdm_2nd = {"source_type": "volume",
+ "uuid": volume["id"],
+ "destination_type": "invalid"}
+ bdm = [bdm_1st, bdm_2nd]
+
+ self.assertRaises(lib_exc.BadRequest,
+ self.create_test_server,
+ image_id=self.image_ref,
+ block_device_mapping_v2=bdm)
+
+ @test.attr(type=['negative'])
@test.idempotent_id('4e72dc2d-44c5-4336-9667-f7972e95c402')
def test_create_with_invalid_network_uuid(self):
# Pass invalid network uuid while creating a server
diff --git a/tempest/api/identity/v3/test_users.py b/tempest/api/identity/v3/test_users.py
index f5b357c..f389a8f 100644
--- a/tempest/api/identity/v3/test_users.py
+++ b/tempest/api/identity/v3/test_users.py
@@ -157,4 +157,4 @@
# If we wait the required time, the user account will be unlocked
time.sleep(CONF.identity.user_lockout_duration + 1)
- self.token.auth(user_id=self.user_id, password=password)
+ self.non_admin_token.auth(user_id=self.user_id, password=password)
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 812c436..23bd628 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -142,6 +142,7 @@
cls.namespaces_client = cls.os.namespaces_client
cls.resource_types_client = cls.os.resource_types_client
cls.namespace_properties_client = cls.os.namespace_properties_client
+ cls.namespace_objects_client = cls.os.namespace_objects_client
cls.schemas_client = cls.os.schemas_client
def create_namespace(cls, namespace_name=None, visibility='public',
diff --git a/tempest/api/image/v1/test_images_negative.py b/tempest/api/image/v1/test_images_negative.py
index d8f103a..3493cc2 100644
--- a/tempest/api/image/v1/test_images_negative.py
+++ b/tempest/api/image/v1/test_images_negative.py
@@ -15,6 +15,7 @@
from tempest.api.image import base
+from tempest.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from tempest import test
@@ -44,7 +45,7 @@
def test_delete_non_existent_image(self):
# Return an error while trying to delete a non-existent image
- non_existent_image_id = '11a22b9-12a9-5555-cc11-00ab112223fa'
+ non_existent_image_id = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound, self.client.delete_image,
non_existent_image_id)
@@ -58,9 +59,9 @@
@test.idempotent_id('950e5054-a3c7-4dee-ada5-e576f1087abd')
def test_delete_image_non_hex_string_id(self):
# Return an error while trying to delete an image with non hex id
- image_id = '11a22b9-120q-5555-cc11-00ab112223gj'
+ invalid_image_id = data_utils.rand_uuid()[:-1] + "j"
self.assertRaises(lib_exc.NotFound, self.client.delete_image,
- image_id)
+ invalid_image_id)
@test.attr(type=['negative'])
@test.idempotent_id('4ed757cd-450c-44b1-9fd1-c819748c650d')
@@ -70,7 +71,8 @@
@test.attr(type=['negative'])
@test.idempotent_id('a4a448ab-3db2-4d2d-b9b2-6a1271241dfe')
- def test_delete_image_id_is_over_35_character_limit(self):
+ def test_delete_image_id_over_character_limit(self):
# Return an error while trying to delete image with id over limit
+ overlimit_image_id = data_utils.rand_uuid() + "1"
self.assertRaises(lib_exc.NotFound, self.client.delete_image,
- '11a22b9-12a9-5555-cc11-00ab112223fa-3fac')
+ overlimit_image_id)
diff --git a/tempest/api/image/v2/test_images_metadefs_namespace_objects.py b/tempest/api/image/v2/test_images_metadefs_namespace_objects.py
new file mode 100644
index 0000000..95d1521
--- /dev/null
+++ b/tempest/api/image/v2/test_images_metadefs_namespace_objects.py
@@ -0,0 +1,73 @@
+# 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.api.image import base
+from tempest.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest import test
+
+
+class MetadataNamespaceObjectsTest(base.BaseV2ImageTest):
+ """Test the Metadata definition namespace objects basic functionality"""
+
+ def _create_namespace_object(self, namespace):
+ object_name = data_utils.rand_name(self.__class__.__name__ + '-object')
+ namespace_object = self.namespace_objects_client.\
+ create_namespace_object(namespace['namespace'], name=object_name)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.namespace_objects_client.delete_namespace_object,
+ namespace['namespace'], object_name)
+ return namespace_object
+
+ @test.idempotent_id('b1a3775e-3b5c-4f6a-a3b4-1ba3574ae718')
+ def test_create_update_delete_meta_namespace_objects(self):
+ # Create a namespace
+ namespace = self.create_namespace()
+ # Create a namespace object
+ body = self._create_namespace_object(namespace)
+ # Update a namespace object
+ up_object_name = data_utils.rand_name('update-object')
+ body = self.namespace_objects_client.update_namespace_object(
+ namespace['namespace'], body['name'],
+ name=up_object_name)
+ self.assertEqual(up_object_name, body['name'])
+ # Delete a namespace object
+ self.namespace_objects_client.delete_namespace_object(
+ namespace['namespace'], up_object_name)
+ # List namespace objects and validate deletion
+ namespace_objects = [
+ namespace_object['name'] for namespace_object in
+ self.namespace_objects_client.list_namespace_objects(
+ namespace['namespace'])['objects']]
+ self.assertNotIn(up_object_name, namespace_objects)
+
+ @test.idempotent_id('a2a3615e-3b5c-3f6a-a2b1-1ba3574ae738')
+ def test_list_meta_namespace_objects(self):
+ # Create a namespace object
+ namespace = self.create_namespace()
+ meta_namespace_object = self._create_namespace_object(namespace)
+ # List namespace objects
+ namespace_objects = [
+ namespace_object['name'] for namespace_object in
+ self.namespace_objects_client.list_namespace_objects(
+ namespace['namespace'])['objects']]
+ self.assertIn(meta_namespace_object['name'], namespace_objects)
+
+ @test.idempotent_id('b1a3674e-3b4c-3f6a-a3b4-1ba3573ca768')
+ def test_show_meta_namespace_objects(self):
+ # Create a namespace object
+ namespace = self.create_namespace()
+ namespace_object = self._create_namespace_object(namespace)
+ # Show a namespace object
+ body = self.namespace_objects_client.show_namespace_object(
+ namespace['namespace'], namespace_object['name'])
+ self.assertEqual(namespace_object['name'], body['name'])
diff --git a/tempest/clients.py b/tempest/clients.py
index 838f128..f99060a 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -127,6 +127,8 @@
self.image_member_client_v2 = self.image_v2.ImageMembersClient()
self.namespaces_client = self.image_v2.NamespacesClient()
self.resource_types_client = self.image_v2.ResourceTypesClient()
+ self.namespace_objects_client = \
+ self.image_v2.NamespaceObjectsClient()
self.schemas_client = self.image_v2.SchemasClient()
self.namespace_properties_client = \
self.image_v2.NamespacePropertiesClient()
diff --git a/tempest/config.py b/tempest/config.py
index 0e45f2e..ea7811d 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -220,8 +220,11 @@
# TODO(rodrigods): Remove the reseller flag when Kilo and Liberty is end
# of life.
cfg.BoolOpt('reseller',
- default=False,
- help='Does the environment support reseller?'),
+ default=True,
+ help='Does the environment support reseller?',
+ deprecated_for_removal=True,
+ deprecated_reason="All supported version of OpenStack now "
+ "supports the 'reseller' feature"),
cfg.BoolOpt('security_compliance',
default=False,
help='Does the environment have the security compliance '
@@ -817,8 +820,11 @@
help="Is the v3 volume API enabled"),
# TODO(ynesenenko): Remove volume_services once liberty-eol happens.
cfg.BoolOpt('volume_services',
- default=False,
- help='Extract correct host info from host@backend')
+ default=True,
+ help='Extract correct host info from host@backend',
+ deprecated_for_removal=True,
+ deprecated_reason='This config switch was added for Liberty '
+ 'which is not supported anymore.')
]
diff --git a/tempest/lib/services/image/v2/__init__.py b/tempest/lib/services/image/v2/__init__.py
index d359d4b..a35ce17 100644
--- a/tempest/lib/services/image/v2/__init__.py
+++ b/tempest/lib/services/image/v2/__init__.py
@@ -15,6 +15,8 @@
from tempest.lib.services.image.v2.image_members_client import \
ImageMembersClient
from tempest.lib.services.image.v2.images_client import ImagesClient
+from tempest.lib.services.image.v2.namespace_objects_client import \
+ NamespaceObjectsClient
from tempest.lib.services.image.v2.namespace_properties_client import \
NamespacePropertiesClient
from tempest.lib.services.image.v2.namespaces_client import NamespacesClient
@@ -22,5 +24,6 @@
ResourceTypesClient
from tempest.lib.services.image.v2.schemas_client import SchemasClient
-__all__ = ['ImageMembersClient', 'ImagesClient', 'NamespacePropertiesClient',
- 'NamespacesClient', 'ResourceTypesClient', 'SchemasClient']
+__all__ = ['ImageMembersClient', 'ImagesClient', 'NamespaceObjectsClient',
+ 'NamespacePropertiesClient', 'NamespacesClient',
+ 'ResourceTypesClient', 'SchemasClient']
diff --git a/tempest/lib/services/image/v2/namespace_objects_client.py b/tempest/lib/services/image/v2/namespace_objects_client.py
new file mode 100644
index 0000000..ac2e63e
--- /dev/null
+++ b/tempest/lib/services/image/v2/namespace_objects_client.py
@@ -0,0 +1,91 @@
+# Copyright 2016 EasyStack.
+# 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 NamespaceObjectsClient(rest_client.RestClient):
+ api_version = "v2"
+
+ def list_namespace_objects(self, namespace, **kwargs):
+ """Lists all namespace objects.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#list-objects
+ """
+ url = 'metadefs/namespaces/%s/objects' % namespace
+ 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 create_namespace_object(self, namespace, **kwargs):
+ """Create a namespace object
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#create-object
+ """
+ url = 'metadefs/namespaces/%s/objects' % namespace
+ data = json.dumps(kwargs)
+ resp, body = self.post(url, data)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_namespace_object(self, namespace, object_name, **kwargs):
+ """Update a namespace object
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#update-object
+ """
+ url = 'metadefs/namespaces/%s/objects/%s' % (namespace, object_name)
+ data = json.dumps(kwargs)
+ resp, body = self.put(url, data)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_namespace_object(self, namespace, object_name):
+ """Show a namespace object
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#show-object
+ """
+ url = 'metadefs/namespaces/%s/objects/%s' % (namespace, object_name)
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_namespace_object(self, namespace, object_name):
+ """Delete a namespace object
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#delete-object
+ """
+ url = 'metadefs/namespaces/%s/objects/%s' % (namespace, object_name)
+ resp, _ = self.delete(url)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
diff --git a/tempest/tests/lib/services/image/v2/test_namespace_object_client.py b/tempest/tests/lib/services/image/v2/test_namespace_object_client.py
new file mode 100644
index 0000000..8d29660
--- /dev/null
+++ b/tempest/tests/lib/services/image/v2/test_namespace_object_client.py
@@ -0,0 +1,210 @@
+# Copyright 2016 EasyStack. 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.image.v2 import namespace_objects_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestNamespaceObjectClient(base.BaseServiceTest):
+ FAKE_CREATE_SHOW_OBJECTS = {
+ "created_at": "2016-09-19T18:20:56Z",
+ "description": "You can configure the CPU limits.",
+ "name": "CPU Limits",
+ "properties": {
+ "quota:cpu_period": {
+ "description": "Specifies the enforcement interval",
+ "maximum": 1000000,
+ "minimum": 1000,
+ "title": "Quota: CPU Period",
+ "type": "integer"
+ },
+ "quota:cpu_quota": {
+ "description": "Specifies the maximum allowed bandwidth ",
+ "title": "Quota: CPU Quota",
+ "type": "integer"
+ },
+ "quota:cpu_shares": {
+ "description": "Specifies the proportional weighted share.",
+ "title": "Quota: CPU Shares",
+ "type": "integer"
+ }
+ },
+ "required": [],
+ "schema": "/v2/schemas/metadefs/object",
+ "self": "/v2/metadefs/namespaces/OS::Compute::Quota/objects/CPU",
+ "updated_at": "2016-09-19T18:20:56Z"
+ }
+
+ FAKE_LIST_OBJECTS = {
+ "objects": [
+ {
+ "created_at": "2016-09-18T18:16:35Z",
+ "description": "You can configure the CPU limits.",
+ "name": "CPU Limits",
+ "properties": {
+ "quota:cpu_period": {
+ "description": "Specifies the enforcement interval ",
+ "maximum": 1000000,
+ "minimum": 1000,
+ "title": "Quota: CPU Period",
+ "type": "integer"
+ },
+ "quota:cpu_quota": {
+ "description": "Specifies the maximum.",
+ "title": "Quota: CPU Quota",
+ "type": "integer"
+ },
+ "quota:cpu_shares": {
+ "description": " Desc.",
+ "title": "Quota: CPU Shares",
+ "type": "integer"
+ }
+ },
+ "required": [],
+ "schema": "/v2/schemas/metadefs/object",
+ "self":
+ "/v2/metadefs/namespaces/OS::Compute::Quota/objects/CPU"
+ },
+ {
+ "created_at": "2016-09-18T18:16:35Z",
+ "description": "Using disk I/O quotas.",
+ "name": "Disk QoS",
+ "properties": {
+ "quota:disk_read_bytes_sec": {
+ "description": "Sets disk I/O quota.",
+ "title": "Quota: Disk read bytes / sec",
+ "type": "integer"
+ },
+ "quota:disk_read_iops_sec": {
+ "description": "Sets disk I/O quota",
+ "title": "Quota: Disk read IOPS / sec",
+ "type": "integer"
+ },
+ "quota:disk_total_bytes_sec": {
+ "description": "Sets disk I/O quota.",
+ "title": "Quota: Disk Total Bytes / sec",
+ "type": "integer"
+ },
+ "quota:disk_total_iops_sec": {
+ "description": "Sets disk I/O quota.",
+ "title": "Quota: Disk Total IOPS / sec",
+ "type": "integer"
+ },
+ "quota:disk_write_bytes_sec": {
+ "description": "Sets disk I/O quota.",
+ "title": "Quota: Disk Write Bytes / sec",
+ "type": "integer"
+ },
+ "quota:disk_write_iops_sec": {
+ "description": "Sets disk I/O quota.",
+ "title": "Quota: Disk Write IOPS / sec",
+ "type": "integer"
+ }
+ },
+ "required": [],
+ "schema": "/v2/schemas/metadefs/object",
+ "self":
+ "/v2/metadefs/namespaces/OS::Compute::Quota/objects/Disk QoS"
+ },
+ ],
+ "schema": "v2/schemas/metadefs/objects"
+ }
+
+ FAKE_UPDATE_OBJECTS = {
+ "description": "You can configure the CPU limits.",
+ "name": "CPU",
+ "properties": {
+ "quota:cpu_shares": {
+ "description": "Specify.",
+ "title": "Quota: CPU Shares",
+ "type": "integer"
+ }
+ },
+ "required": []
+ }
+
+ def setUp(self):
+ super(TestNamespaceObjectClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = namespace_objects_client.NamespaceObjectsClient(
+ fake_auth, 'image', 'regionOne')
+
+ def _test_create_namespace_objects(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_namespace_object,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_CREATE_SHOW_OBJECTS,
+ bytes_body, status=201,
+ namespace="OS::Compute::Hypervisor",
+ object_name="OS::Glance::Image")
+
+ def _test_list_namespace_objects(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_namespace_objects,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_OBJECTS,
+ bytes_body,
+ namespace="OS::Compute::Hypervisor")
+
+ def _test_show_namespace_objects(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_namespace_object,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_CREATE_SHOW_OBJECTS,
+ bytes_body,
+ namespace="OS::Compute::Hypervisor",
+ object_name="OS::Glance::Image")
+
+ def _test_update_namespace_objects(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_namespace_object,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ self.FAKE_UPDATE_OBJECTS,
+ bytes_body,
+ namespace="OS::Compute::Hypervisor",
+ object_name="OS::Glance::Image",
+ name="CPU")
+
+ def test_create_namespace_object_with_str_body(self):
+ self._test_create_namespace_objects()
+
+ def test_create_namespace_object_with_bytes_body(self):
+ self._test_create_namespace_objects(bytes_body=True)
+
+ def test_list_namespace_object_with_str_body(self):
+ self._test_list_namespace_objects()
+
+ def test_list_namespace_object_with_bytes_body(self):
+ self._test_list_namespace_objects(bytes_body=True)
+
+ def test_show_namespace_object_with_str_body(self):
+ self._test_show_namespace_objects()
+
+ def test_show_namespace_object_with_bytes_body(self):
+ self._test_show_namespace_objects(bytes_body=True)
+
+ def test_update_namespace_object_with_str_body(self):
+ self._test_update_namespace_objects()
+
+ def test_update_namespace_object_with_bytes_body(self):
+ self._test_update_namespace_objects(bytes_body=True)
+
+ def test_delete_namespace_objects(self):
+ self.check_service_client_function(
+ self.client.delete_namespace_object,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {}, namespace="OS::Compute::Hypervisor",
+ object_name="OS::Glance::Image",
+ status=204)