Merge "Fixed project lists for retrieving tempest plugins"
diff --git a/releasenotes/notes/add-identity-v3-clients-for-os-ep-filter-api-endpoint-groups-3518a90bbb731d0f.yaml b/releasenotes/notes/add-identity-v3-clients-for-os-ep-filter-api-endpoint-groups-3518a90bbb731d0f.yaml
new file mode 100644
index 0000000..1dc33aa
--- /dev/null
+++ b/releasenotes/notes/add-identity-v3-clients-for-os-ep-filter-api-endpoint-groups-3518a90bbb731d0f.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ Defines the identity v3 OS-EP-FILTER EndPoint Groups API client.
+ This client manages Create, Get, Update, Check, List, and Delete
+ of EndPoint Group.
+
diff --git a/releasenotes/notes/add-manage-snapshot-ref-config-option-67efd04897335b67.yaml b/releasenotes/notes/add-manage-snapshot-ref-config-option-67efd04897335b67.yaml
new file mode 100644
index 0000000..bc7bcc8
--- /dev/null
+++ b/releasenotes/notes/add-manage-snapshot-ref-config-option-67efd04897335b67.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ A new config option 'manage_snapshot_ref' is added in the volume section,
+ to specify snapshot ref parameter for different storage backend drivers
+ when managing an existing snapshot. By default it is set to fit the LVM
+ driver.
diff --git a/releasenotes/notes/identity-token-client-8aaef74b1d61090a.yaml b/releasenotes/notes/identity-token-client-8aaef74b1d61090a.yaml
new file mode 100644
index 0000000..d94de3e
--- /dev/null
+++ b/releasenotes/notes/identity-token-client-8aaef74b1d61090a.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Add additional API endpoints to the identity v2 client token API:
+ - list_endpoints_for_token
+ - check_token_existence
diff --git a/releasenotes/notes/network-tag-client-f4614029af7927f0.yaml b/releasenotes/notes/network-tag-client-f4614029af7927f0.yaml
new file mode 100644
index 0000000..9af57b1
--- /dev/null
+++ b/releasenotes/notes/network-tag-client-f4614029af7927f0.yaml
@@ -0,0 +1,8 @@
+---
+features:
+ - |
+ Define v2.0 ``tags_client`` for the network service as a library
+ interface, allowing other projects to use this module as a stable
+ library without maintenance changes.
+
+ * tags_client(v2.0)
diff --git a/requirements.txt b/requirements.txt
index 9f57ee1..259a4cf 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,7 +9,7 @@
netaddr!=0.7.16,>=0.7.13 # BSD
testrepository>=0.0.18 # Apache-2.0/BSD
oslo.concurrency>=3.8.0 # Apache-2.0
-oslo.config>=4.0.0 # Apache-2.0
+oslo.config!=4.3.0,!=4.4.0,>=4.0.0 # Apache-2.0
oslo.log>=3.22.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
oslo.utils>=3.20.0 # Apache-2.0
@@ -20,6 +20,6 @@
stevedore>=1.20.0 # Apache-2.0
PrettyTable<0.8,>=0.7.1 # BSD
os-testr>=0.8.0 # Apache-2.0
-urllib3>=1.15.1 # MIT
+urllib3>=1.21.1 # MIT
debtcollector>=1.2.0 # Apache-2.0
unittest2 # BSD
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 83447b6..5987d39 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -80,11 +80,11 @@
@decorators.idempotent_id('3b7c6fe4-dfe7-477c-9243-b06359db51e6')
def test_create_image_specify_multibyte_character_image_name(self):
# prefix character is:
- # http://www.fileformat.info/info/unicode/char/1F4A9/index.htm
+ # http://unicode.org/cldr/utility/character.jsp?a=20A1
- # We use a string with 3 byte utf-8 character due to bug
- # #1370954 in glance which will 500 if mysql is used as the
- # backend and it attempts to store a 4 byte utf-8 character
+ # We use a string with 3 byte utf-8 character due to nova/glance which
+ # will return 400(Bad Request) if we attempt to send a name which has
+ # 4 byte utf-8 character.
utf8_name = data_utils.rand_name(b'\xe2\x82\xa1'.decode('utf-8'))
body = self.client.create_image(self.server_id, name=utf8_name)
image_id = data_utils.parse_image_id(body.response['location'])
diff --git a/tempest/api/identity/admin/v2/test_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
index b4c9389..6b30d23 100644
--- a/tempest/api/identity/admin/v2/test_tokens.py
+++ b/tempest/api/identity/admin/v2/test_tokens.py
@@ -14,14 +14,18 @@
# under the License.
from tempest.api.identity import base
+from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+CONF = config.CONF
class TokensTestJSON(base.BaseIdentityV2AdminTest):
@decorators.idempotent_id('453ad4d5-e486-4b2f-be72-cffc8149e586')
- def test_create_get_delete_token(self):
+ def test_create_check_get_delete_token(self):
# get a token by username and password
user_name = data_utils.rand_name(name='user')
user_password = data_utils.rand_password()
@@ -40,6 +44,7 @@
tenant['name'])
# Perform GET Token
token_id = body['token']['id']
+ self.client.check_token_existence(token_id)
token_details = self.client.show_token(token_id)['access']
self.assertEqual(token_id, token_details['token']['id'])
self.assertEqual(user['id'], token_details['user']['id'])
@@ -48,6 +53,9 @@
token_details['token']['tenant']['name'])
# then delete the token
self.client.delete_token(token_id)
+ self.assertRaises(lib_exc.NotFound,
+ self.client.check_token_existence,
+ token_id)
@decorators.idempotent_id('25ba82ee-8a32-4ceb-8f50-8b8c71e8765e')
def test_rescope_token(self):
@@ -101,3 +109,25 @@
# Use the unscoped token to get a token scoped to tenant2
body = self.token_client.auth_token(token_id,
tenant=tenant2_name)
+
+ @decorators.idempotent_id('ca3ea6f7-ed08-4a61-adbd-96906456ad31')
+ def test_list_endpoints_for_token(self):
+ # get a token for the user
+ creds = self.os_primary.credentials
+ username = creds.username
+ password = creds.password
+ tenant_name = creds.tenant_name
+ token = self.token_client.auth(username,
+ password,
+ tenant_name)['token']
+ endpoints = self.client.list_endpoints_for_token(
+ token['id'])['endpoints']
+ self.assertIsInstance(endpoints, list)
+ # Store list of service names
+ service_names = [e['name'] for e in endpoints]
+ # Get the list of available services.
+ available_services = [s[0] for s in list(
+ CONF.service_available.items()) if s[1] is True]
+ # Verify that all available services are present.
+ for service in available_services:
+ self.assertIn(service, service_names)
diff --git a/tempest/api/identity/admin/v2/test_tokens_negative.py b/tempest/api/identity/admin/v2/test_tokens_negative.py
new file mode 100644
index 0000000..eb3e365
--- /dev/null
+++ b/tempest/api/identity/admin/v2/test_tokens_negative.py
@@ -0,0 +1,38 @@
+# Copyright 2017 AT&T Corporation
+# 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.api.identity import base
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+
+class TokensAdminTestNegative(base.BaseIdentityV2AdminTest):
+
+ credentials = ['primary', 'admin', 'alt']
+
+ @decorators.attr(type=['negative'])
+ @decorators.idempotent_id('a0a0a600-4292-4364-99c5-922c834fdf05')
+ def test_check_token_existence_negative(self):
+ creds = self.os_primary.credentials
+ creds_alt = self.os_alt.credentials
+ username = creds.username
+ password = creds.password
+ tenant_name = creds.tenant_name
+ alt_tenant_name = creds_alt.tenant_name
+ body = self.token_client.auth(username, password, tenant_name)
+ self.assertRaises(lib_exc.Unauthorized,
+ self.client.check_token_existence,
+ body['token']['id'],
+ belongsTo=alt_tenant_name)
diff --git a/tempest/api/identity/admin/v3/test_endpoint_groups.py b/tempest/api/identity/admin/v3/test_endpoint_groups.py
new file mode 100644
index 0000000..5cd456c
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_endpoint_groups.py
@@ -0,0 +1,157 @@
+# Copyright 2017 AT&T Corporation.
+# 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.api.identity import base
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+
+class EndPointGroupsTest(base.BaseIdentityV3AdminTest):
+
+ @classmethod
+ def setup_clients(cls):
+ super(EndPointGroupsTest, cls).setup_clients()
+ cls.client = cls.endpoint_groups_client
+
+ @classmethod
+ def resource_setup(cls):
+ super(EndPointGroupsTest, cls).resource_setup()
+ cls.service_ids = list()
+ cls.endpoint_groups = list()
+
+ # Create endpoint group so as to use it for LIST test
+ service_id = cls._create_service()
+
+ name = data_utils.rand_name('service_group')
+ description = data_utils.rand_name('description')
+ filters = {'service_id': service_id}
+
+ endpoint_group = cls.client.create_endpoint_group(
+ name=name,
+ description=description,
+ filters=filters)['endpoint_group']
+
+ cls.endpoint_groups.append(endpoint_group)
+
+ @classmethod
+ def resource_cleanup(cls):
+ for e in cls.endpoint_groups:
+ cls.client.delete_endpoint_group(e['id'])
+ for s in cls.service_ids:
+ cls.services_client.delete_service(s)
+ super(EndPointGroupsTest, cls).resource_cleanup()
+
+ @classmethod
+ def _create_service(self):
+ s_name = data_utils.rand_name('service')
+ s_type = data_utils.rand_name('type')
+ s_description = data_utils.rand_name('description')
+ service_data = (
+ self.services_client.create_service(name=s_name,
+ type=s_type,
+ description=s_description))
+
+ service_id = service_data['service']['id']
+ self.service_ids.append(service_id)
+ return service_id
+
+ @decorators.idempotent_id('7c69e7a1-f865-402d-a2ea-44493017315a')
+ def test_create_list_show_check_delete_endpoint_group(self):
+ service_id = self._create_service()
+ name = data_utils.rand_name('service_group')
+ description = data_utils.rand_name('description')
+ filters = {'service_id': service_id}
+
+ endpoint_group = self.client.create_endpoint_group(
+ name=name,
+ description=description,
+ filters=filters)['endpoint_group']
+
+ self.endpoint_groups.append(endpoint_group)
+
+ # Asserting created endpoint group response body
+ self.assertIn('id', endpoint_group)
+ self.assertEqual(name, endpoint_group['name'])
+ self.assertEqual(description, endpoint_group['description'])
+
+ # Checking if endpoint groups are present in the list of endpoints
+ # Note that there are two endpoint groups in the list, one created
+ # in the resource setup, one created in this test case.
+ fetched_endpoints = \
+ self.client.list_endpoint_groups()['endpoint_groups']
+
+ missing_endpoints = \
+ [e for e in self.endpoint_groups if e not in fetched_endpoints]
+
+ # Asserting LIST endpoints
+ self.assertEmpty(missing_endpoints,
+ "Failed to find endpoint %s in fetched list" %
+ ', '.join(str(e) for e in missing_endpoints))
+
+ # Show endpoint group
+ fetched_endpoint = self.client.show_endpoint_group(
+ endpoint_group['id'])['endpoint_group']
+
+ # Asserting if the attributes of endpoint group are the same
+ self.assertEqual(service_id,
+ fetched_endpoint['filters']['service_id'])
+ for attr in ('id', 'name', 'description'):
+ self.assertEqual(endpoint_group[attr], fetched_endpoint[attr])
+
+ # Check endpoint group
+ self.client.check_endpoint_group(endpoint_group['id'])
+
+ # Deleting the endpoint group created in this method
+ self.client.delete_endpoint_group(endpoint_group['id'])
+ self.endpoint_groups.remove(endpoint_group)
+
+ # Checking whether endpoint group is deleted successfully
+ fetched_endpoints = \
+ self.client.list_endpoint_groups()['endpoint_groups']
+ fetched_endpoint_ids = [e['id'] for e in fetched_endpoints]
+ self.assertNotIn(endpoint_group['id'], fetched_endpoint_ids)
+
+ @decorators.idempotent_id('51c8fc38-fa84-4e76-b5b6-6fc37770fb26')
+ def test_update_endpoint_group(self):
+ # Creating an endpoint group so as to check update endpoint group
+ # with new values
+ service1_id = self._create_service()
+ name = data_utils.rand_name('service_group')
+ description = data_utils.rand_name('description')
+ filters = {'service_id': service1_id}
+
+ endpoint_group = self.client.create_endpoint_group(
+ name=name,
+ description=description,
+ filters=filters)['endpoint_group']
+ self.endpoint_groups.append(endpoint_group)
+
+ # Creating new attr values to update endpoint group
+ service2_id = self._create_service()
+ name2 = data_utils.rand_name('service_group2')
+ description2 = data_utils.rand_name('description2')
+ filters = {'service_id': service2_id}
+
+ # Updating endpoint group with new attr values
+ updated_endpoint_group = self.client.update_endpoint_group(
+ endpoint_group['id'],
+ name=name2,
+ description=description2,
+ filters=filters)['endpoint_group']
+
+ self.assertEqual(name2, updated_endpoint_group['name'])
+ self.assertEqual(description2, updated_endpoint_group['description'])
+ self.assertEqual(service2_id,
+ updated_endpoint_group['filters']['service_id'])
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 785485b..3bc6ce1 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -225,6 +225,7 @@
cls.oauth_consumers_client = cls.os_admin.oauth_consumers_client
cls.domain_config_client = cls.os_admin.domain_config_client
cls.endpoint_filter_client = cls.os_admin.endpoint_filter_client
+ cls.endpoint_groups_client = cls.os_admin.endpoint_groups_client
if CONF.identity.admin_domain_scope:
# NOTE(andreaf) When keystone policy requires it, the identity
diff --git a/tempest/api/identity/v3/test_tokens.py b/tempest/api/identity/v3/test_tokens.py
index 042c821..4c72d82 100644
--- a/tempest/api/identity/v3/test_tokens.py
+++ b/tempest/api/identity/v3/test_tokens.py
@@ -15,12 +15,39 @@
from oslo_utils import timeutils
import six
+
from tempest.api.identity import base
from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
class TokensV3Test(base.BaseIdentityV3Test):
+ @decorators.idempotent_id('a9512ac3-3909-48a4-b395-11f438e16260')
+ def test_validate_token(self):
+ creds = self.os_primary.credentials
+ user_id = creds.user_id
+ username = creds.username
+ password = creds.password
+ user_domain_id = creds.user_domain_id
+ # GET and validate token
+ subject_token, token_body = self.non_admin_token.get_token(
+ user_id=user_id,
+ username=username,
+ user_domain_id=user_domain_id,
+ password=password,
+ auth_data=True)
+ authenticated_token = self.non_admin_client.show_token(
+ subject_token)['token']
+ # sanity checking to make sure they are indeed the same token
+ self.assertEqual(authenticated_token, token_body)
+ # test to see if token has been properly authenticated
+ self.assertEqual(authenticated_token['user']['id'], user_id)
+ self.assertEqual(authenticated_token['user']['name'], username)
+ self.non_admin_client.delete_token(subject_token)
+ self.assertRaises(
+ lib_exc.NotFound, self.non_admin_client.show_token, subject_token)
+
@decorators.idempotent_id('6f8e4436-fc96-4282-8122-e41df57197a9')
def test_create_token(self):
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 8775495..6bec0d7 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -83,6 +83,7 @@
cls.os_primary.security_group_rules_client)
cls.network_versions_client = cls.os_primary.network_versions_client
cls.service_providers_client = cls.os_primary.service_providers_client
+ cls.tags_client = cls.os_primary.tags_client
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/network/test_tags.py b/tempest/api/network/test_tags.py
new file mode 100644
index 0000000..1f3a7c4
--- /dev/null
+++ b/tempest/api/network/test_tags.py
@@ -0,0 +1,90 @@
+# Copyright 2017 AT&T Corporation.
+# 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.api.network import base
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+from tempest import test
+
+
+class TagsTest(base.BaseNetworkTest):
+ """Tests the following operations in the tags API:
+
+ Update all tags.
+ Delete all tags.
+ Check tag existence.
+ Create a tag.
+ List tags.
+ Remove a tag.
+
+ v2.0 of the Neutron API is assumed. The tag extension allows users to set
+ tags on their networks. The extension supports networks only.
+ """
+
+ @classmethod
+ def skip_checks(cls):
+ super(TagsTest, cls).skip_checks()
+ if not test.is_extension_enabled('tag', 'network'):
+ msg = "tag extension not enabled."
+ raise cls.skipException(msg)
+
+ @classmethod
+ def resource_setup(cls):
+ super(TagsTest, cls).resource_setup()
+ cls.network = cls.create_network()
+
+ @decorators.idempotent_id('ee76bfaf-ac94-4d74-9ecc-4bbd4c583cb1')
+ def test_create_list_show_update_delete_tags(self):
+ # Validate that creating a tag on a network resource works.
+ tag_name = data_utils.rand_name(self.__class__.__name__ + '-Tag')
+ self.tags_client.create_tag('networks', self.network['id'], tag_name)
+ self.addCleanup(self.tags_client.delete_all_tags, 'networks',
+ self.network['id'])
+ self.tags_client.check_tag_existence('networks', self.network['id'],
+ tag_name)
+
+ # Validate that listing tags on a network resource works.
+ retrieved_tags = self.tags_client.list_tags(
+ 'networks', self.network['id'])['tags']
+ self.assertEqual([tag_name], retrieved_tags)
+
+ # Generate 3 new tag names.
+ replace_tags = [data_utils.rand_name(
+ self.__class__.__name__ + '-Tag') for _ in range(3)]
+
+ # Replace the current tag with the 3 new tags and validate that the
+ # network resource has the 3 new tags.
+ updated_tags = self.tags_client.update_all_tags(
+ 'networks', self.network['id'], replace_tags)['tags']
+ self.assertEqual(3, len(updated_tags))
+ self.assertEqual(set(replace_tags), set(updated_tags))
+
+ # Delete the first tag and check that it has been removed.
+ self.tags_client.delete_tag(
+ 'networks', self.network['id'], replace_tags[0])
+ self.assertRaises(lib_exc.NotFound,
+ self.tags_client.check_tag_existence, 'networks',
+ self.network['id'], replace_tags[0])
+ for i in range(1, 3):
+ self.tags_client.check_tag_existence(
+ 'networks', self.network['id'], replace_tags[i])
+
+ # Delete all the remaining tags and check that they have been removed.
+ self.tags_client.delete_all_tags('networks', self.network['id'])
+ for i in range(1, 3):
+ self.assertRaises(lib_exc.NotFound,
+ self.tags_client.check_tag_existence, 'networks',
+ self.network['id'], replace_tags[i])
diff --git a/tempest/api/volume/admin/test_snapshot_manage.py b/tempest/api/volume/admin/test_snapshot_manage.py
index 9f96194..6c09042 100644
--- a/tempest/api/volume/admin/test_snapshot_manage.py
+++ b/tempest/api/volume/admin/test_snapshot_manage.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import testtools
-
from tempest.api.volume import base
from tempest.common import waiters
from tempest import config
@@ -32,9 +30,18 @@
managed by Cinder from a storage back end to Cinder
"""
+ @classmethod
+ def skip_checks(cls):
+ super(SnapshotManageAdminTest, cls).skip_checks()
+
+ if not CONF.volume_feature_enabled.manage_snapshot:
+ raise cls.skipException("Manage snapshot tests are disabled")
+
+ if len(CONF.volume.manage_snapshot_ref) != 2:
+ raise cls.skipException("Manage snapshot ref is not correctly "
+ "configured")
+
@decorators.idempotent_id('0132f42d-0147-4b45-8501-cc504bbf7810')
- @testtools.skipUnless(CONF.volume_feature_enabled.manage_snapshot,
- "Manage snapshot tests are disabled")
def test_unmanage_manage_snapshot(self):
# Create a volume
volume = self.create_volume()
@@ -48,15 +55,13 @@
self.admin_snapshots_client.unmanage_snapshot(snapshot['id'])
self.admin_snapshots_client.wait_for_resource_deletion(snapshot['id'])
- # Fetch snapshot ids
- snapshot_list = [
- snap['id'] for snap in
- self.snapshots_client.list_snapshots()['snapshots']
- ]
+ # Verify the original snapshot does not exist in snapshot list
+ params = {'all_tenants': 1}
+ all_snapshots = self.admin_snapshots_client.list_snapshots(
+ detail=True, params=params)['snapshots']
+ self.assertNotIn(snapshot['id'], [v['id'] for v in all_snapshots])
- # Verify snapshot does not exist in snapshot list
- self.assertNotIn(snapshot['id'], snapshot_list)
-
+ # Manage the snapshot
name = data_utils.rand_name(self.__class__.__name__ +
'-Managed-Snapshot')
description = data_utils.rand_name(self.__class__.__name__ +
@@ -64,12 +69,16 @@
metadata = {"manage-snap-meta1": "value1",
"manage-snap-meta2": "value2",
"manage-snap-meta3": "value3"}
-
- # Manage the snapshot
- snapshot_ref = '_snapshot-%s' % snapshot['id']
+ snapshot_ref = {
+ 'volume_id': volume['id'],
+ 'ref': {CONF.volume.manage_snapshot_ref[0]:
+ CONF.volume.manage_snapshot_ref[1] % snapshot['id']},
+ 'name': name,
+ 'description': description,
+ 'metadata': metadata
+ }
new_snapshot = self.admin_snapshot_manage_client.manage_snapshot(
- volume_id=volume['id'], ref={'source-name': snapshot_ref},
- name=name, description=description, metadata=metadata)['snapshot']
+ **snapshot_ref)['snapshot']
self.addCleanup(self.delete_snapshot, new_snapshot['id'],
self.admin_snapshots_client)
@@ -80,9 +89,8 @@
# Verify the managed snapshot has the expected parent volume
# and the expected field values.
- new_snap_info = self.admin_snapshots_client.show_snapshot(
+ new_snapshot_info = self.admin_snapshots_client.show_snapshot(
new_snapshot['id'])['snapshot']
- self.assertEqual(volume['id'], new_snap_info['volume_id'])
- self.assertEqual(name, new_snap_info['name'])
- self.assertEqual(description, new_snap_info['description'])
- self.assertEqual(metadata, new_snap_info['metadata'])
+ self.assertEqual(snapshot['size'], new_snapshot_info['size'])
+ for key in ['volume_id', 'name', 'description', 'metadata']:
+ self.assertEqual(snapshot_ref[key], new_snapshot_info[key])
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index da4324a..4b4aeec 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -118,9 +118,8 @@
name=backup_name, force=True)
self.assertEqual(backup_name, backup['name'])
- @testtools.skipUnless(CONF.service_available.glance,
- "Glance is not available")
@decorators.idempotent_id('2a8ba340-dff2-4511-9db7-646f07156b15')
+ @test.services('image')
def test_bootable_volume_backup_and_restore(self):
# Create volume from image
img_uuid = CONF.compute.image_ref
diff --git a/tempest/api/volume/test_volumes_clone.py b/tempest/api/volume/test_volumes_clone.py
index a6bbb0a..4c13375 100644
--- a/tempest/api/volume/test_volumes_clone.py
+++ b/tempest/api/volume/test_volumes_clone.py
@@ -13,11 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-import testtools
-
from tempest.api.volume import base
from tempest import config
from tempest.lib import decorators
+from tempest import test
CONF = config.CONF
@@ -47,9 +46,8 @@
self.assertEqual(volume['source_volid'], src_vol['id'])
self.assertEqual(volume['size'], src_size + 1)
- @testtools.skipUnless(CONF.service_available.glance,
- "Glance is not available")
@decorators.idempotent_id('cbbcd7c6-5a6c-481a-97ac-ca55ab715d16')
+ @test.services('image')
def test_create_from_bootable_volume(self):
# Create volume from image
img_uuid = CONF.compute.image_ref
diff --git a/tempest/clients.py b/tempest/clients.py
index 7b6cc19..8ad6e92 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -79,6 +79,7 @@
self.security_groups_client = self.network.SecurityGroupsClient()
self.network_versions_client = self.network.NetworkVersionsClient()
self.service_providers_client = self.network.ServiceProvidersClient()
+ self.tags_client = self.network.TagsClient()
def _set_image_clients(self):
if CONF.service_available.glance:
@@ -203,6 +204,8 @@
**params_v3)
self.endpoint_filter_client = \
self.identity_v3.EndPointsFilterClient(**params_v3)
+ self.endpoint_groups_client = self.identity_v3.EndPointGroupsClient(
+ **params_v3)
# Token clients do not use the catalog. They only need default_params.
# They read auth_url, so they should only be set if the corresponding
diff --git a/tempest/config.py b/tempest/config.py
index 989d53a..fbe0a1b 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -768,6 +768,12 @@
"It contains two elements, the first is ref type "
"(like 'source-name', 'source-id', etc), the second is "
"volume name template used in storage backend"),
+ cfg.ListOpt('manage_snapshot_ref',
+ default=['source-name', '_snapshot-%s'],
+ help="A reference to existing snapshot for snapshot manage. "
+ "It contains two elements, the first is ref type "
+ "(like 'source-name', 'source-id', etc), the second is "
+ "snapshot name template used in storage backend"),
cfg.StrOpt('min_microversion',
default=None,
help="Lower version of the test target microversion range. "
diff --git a/tempest/lib/common/utils/linux/remote_client.py b/tempest/lib/common/utils/linux/remote_client.py
index 64d6be2..aef2ff3 100644
--- a/tempest/lib/common/utils/linux/remote_client.py
+++ b/tempest/lib/common/utils/linux/remote_client.py
@@ -28,29 +28,37 @@
def wrapper(self, *args, **kwargs):
try:
return function(self, *args, **kwargs)
- except tempest.lib.exceptions.SSHTimeout:
- try:
- original_exception = sys.exc_info()
- caller = test_utils.find_test_caller() or "not found"
- if self.server:
- msg = 'Caller: %s. Timeout trying to ssh to server %s'
- LOG.debug(msg, caller, self.server)
- if self.console_output_enabled and self.servers_client:
- try:
- msg = 'Console log for server %s: %s'
- console_log = (
- self.servers_client.get_console_output(
- self.server['id'])['output'])
- LOG.debug(msg, self.server['id'], console_log)
- except Exception:
- msg = 'Could not get console_log for server %s'
- LOG.debug(msg, self.server['id'])
- # re-raise the original ssh timeout exception
- six.reraise(*original_exception)
- finally:
- # Delete the traceback to avoid circular references
- _, _, trace = original_exception
- del trace
+ except Exception as e:
+ caller = test_utils.find_test_caller() or "not found"
+ if not isinstance(e, tempest.lib.exceptions.SSHTimeout):
+ message = ('Initializing SSH connection to %(ip)s failed. '
+ 'Error: %(error)s' % {'ip': self.ip_address,
+ 'error': e})
+ message = '(%s) %s' % (caller, message)
+ LOG.error(message)
+ raise
+ else:
+ try:
+ original_exception = sys.exc_info()
+ if self.server:
+ msg = 'Caller: %s. Timeout trying to ssh to server %s'
+ LOG.debug(msg, caller, self.server)
+ if self.console_output_enabled and self.servers_client:
+ try:
+ msg = 'Console log for server %s: %s'
+ console_log = (
+ self.servers_client.get_console_output(
+ self.server['id'])['output'])
+ LOG.debug(msg, self.server['id'], console_log)
+ except Exception:
+ msg = 'Could not get console_log for server %s'
+ LOG.debug(msg, self.server['id'])
+ # re-raise the original ssh timeout exception
+ six.reraise(*original_exception)
+ finally:
+ # Delete the traceback to avoid circular references
+ _, _, trace = original_exception
+ del trace
return wrapper
@@ -78,6 +86,7 @@
"""
self.server = server
self.servers_client = servers_client
+ self.ip_address = ip_address
self.console_output_enabled = console_output_enabled
self.ssh_shell_prologue = ssh_shell_prologue
self.ping_count = ping_count
diff --git a/tempest/lib/services/identity/v2/identity_client.py b/tempest/lib/services/identity/v2/identity_client.py
index 6caff0e..c610d65 100644
--- a/tempest/lib/services/identity/v2/identity_client.py
+++ b/tempest/lib/services/identity/v2/identity_client.py
@@ -11,6 +11,7 @@
# 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
@@ -45,3 +46,24 @@
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
+
+ def list_endpoints_for_token(self, token_id):
+ """List endpoints for a token """
+ resp, body = self.get("tokens/%s/endpoints" % token_id)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_token_existence(self, token_id, **params):
+ """Validates a token and confirms that it belongs to a tenant.
+
+ For a full list of available parameters, please refer to the
+ official API reference:
+ https://developer.openstack.org/api-ref/identity/v2-admin/#validate-token
+ """
+ url = "tokens/%s" % token_id
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+ resp, body = self.head(url)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/identity/v3/__init__.py b/tempest/lib/services/identity/v3/__init__.py
index 6f498d9..ce607ff 100644
--- a/tempest/lib/services/identity/v3/__init__.py
+++ b/tempest/lib/services/identity/v3/__init__.py
@@ -19,6 +19,8 @@
from tempest.lib.services.identity.v3.domains_client import DomainsClient
from tempest.lib.services.identity.v3.endpoint_filter_client import \
EndPointsFilterClient
+from tempest.lib.services.identity.v3.endpoint_groups_client import \
+ EndPointGroupsClient
from tempest.lib.services.identity.v3.endpoints_client import EndPointsClient
from tempest.lib.services.identity.v3.groups_client import GroupsClient
from tempest.lib.services.identity.v3.identity_client import IdentityClient
@@ -39,8 +41,9 @@
from tempest.lib.services.identity.v3.versions_client import VersionsClient
__all__ = ['CredentialsClient', 'DomainsClient', 'DomainConfigurationClient',
- 'EndPointsClient', 'EndPointsFilterClient', 'GroupsClient',
- 'IdentityClient', 'InheritedRolesClient', 'OAUTHConsumerClient',
- 'PoliciesClient', 'ProjectsClient', 'RegionsClient',
- 'RoleAssignmentsClient', 'RolesClient', 'ServicesClient',
- 'V3TokenClient', 'TrustsClient', 'UsersClient', 'VersionsClient']
+ 'EndPointGroupsClient', 'EndPointsClient', 'EndPointsFilterClient',
+ 'GroupsClient', 'IdentityClient', 'InheritedRolesClient',
+ 'OAUTHConsumerClient', 'PoliciesClient', 'ProjectsClient',
+ 'RegionsClient', 'RoleAssignmentsClient', 'RolesClient',
+ 'ServicesClient', 'V3TokenClient', 'TrustsClient', 'UsersClient',
+ 'VersionsClient']
diff --git a/tempest/lib/services/identity/v3/endpoint_groups_client.py b/tempest/lib/services/identity/v3/endpoint_groups_client.py
new file mode 100644
index 0000000..723aeaa
--- /dev/null
+++ b/tempest/lib/services/identity/v3/endpoint_groups_client.py
@@ -0,0 +1,78 @@
+# Copyright 2017 AT&T Corporation.
+# 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 tempest.lib.common import rest_client
+
+
+class EndPointGroupsClient(rest_client.RestClient):
+ api_version = "v3"
+
+ def create_endpoint_group(self, **kwargs):
+ """Create endpoint group.
+
+ For a full list of available parameters, please refer to the
+ official API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/#create-endpoint-group
+ """
+ post_body = json.dumps({'endpoint_group': kwargs})
+ resp, body = self.post('OS-EP-FILTER/endpoint_groups', post_body)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_endpoint_group(self, endpoint_group_id, **kwargs):
+ """Update endpoint group.
+
+ For a full list of available parameters, please refer to the
+ official API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/#update-endpoint-group
+ """
+ post_body = json.dumps({'endpoint_group': kwargs})
+ resp, body = self.patch(
+ 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id, post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_endpoint_group(self, endpoint_group_id):
+ """Delete endpoint group."""
+ resp_header, resp_body = self.delete(
+ 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id)
+ self.expected_success(204, resp_header.status)
+ return rest_client.ResponseBody(resp_header, resp_body)
+
+ def show_endpoint_group(self, endpoint_group_id):
+ """Get endpoint group."""
+ resp_header, resp_body = self.get(
+ 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id)
+ self.expected_success(200, resp_header.status)
+ resp_body = json.loads(resp_body)
+ return rest_client.ResponseBody(resp_header, resp_body)
+
+ def check_endpoint_group(self, endpoint_group_id):
+ """Check endpoint group."""
+ resp_header, resp_body = self.head(
+ 'OS-EP-FILTER/endpoint_groups/%s' % endpoint_group_id)
+ self.expected_success(200, resp_header.status)
+ return rest_client.ResponseBody(resp_header, resp_body)
+
+ def list_endpoint_groups(self):
+ """Get endpoint groups."""
+ resp_header, resp_body = self.get('OS-EP-FILTER/endpoint_groups')
+ self.expected_success(200, resp_header.status)
+ resp_body = json.loads(resp_body)
+ return rest_client.ResponseBody(resp_header, resp_body)
diff --git a/tempest/lib/services/network/__init__.py b/tempest/lib/services/network/__init__.py
index 19e5463..419e593 100644
--- a/tempest/lib/services/network/__init__.py
+++ b/tempest/lib/services/network/__init__.py
@@ -31,11 +31,12 @@
ServiceProvidersClient
from tempest.lib.services.network.subnetpools_client import SubnetpoolsClient
from tempest.lib.services.network.subnets_client import SubnetsClient
+from tempest.lib.services.network.tags_client import TagsClient
from tempest.lib.services.network.versions_client import NetworkVersionsClient
__all__ = ['AgentsClient', 'ExtensionsClient', 'FloatingIPsClient',
'MeteringLabelRulesClient', 'MeteringLabelsClient',
- 'NetworksClient', 'PortsClient', 'QuotasClient', 'RoutersClient',
- 'SecurityGroupRulesClient', 'SecurityGroupsClient',
- 'ServiceProvidersClient', 'SubnetpoolsClient', 'SubnetsClient',
- 'NetworkVersionsClient']
+ 'NetworksClient', 'NetworkVersionsClient', 'PortsClient',
+ 'QuotasClient', 'RoutersClient', 'SecurityGroupRulesClient',
+ 'SecurityGroupsClient', 'ServiceProvidersClient',
+ 'SubnetpoolsClient', 'SubnetsClient', 'TagsClient']
diff --git a/tempest/lib/services/network/tags_client.py b/tempest/lib/services/network/tags_client.py
new file mode 100644
index 0000000..20c2c11
--- /dev/null
+++ b/tempest/lib/services/network/tags_client.py
@@ -0,0 +1,88 @@
+# Copyright 2017 AT&T Corporation.
+# 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 tempest.lib.common import rest_client
+from tempest.lib.services.network import base
+
+
+class TagsClient(base.BaseNetworkClient):
+
+ def create_tag(self, resource_type, resource_id, tag):
+ """Adds a tag on the resource.
+
+ For more information, please refer to the official API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#add-a-tag
+ """
+ # NOTE(felipemonteiro): Cannot use ``update_resource`` method because
+ # this API requires self.put but returns 201 instead of 200 expected
+ # by ``update_resource``.
+ uri = '%s/%s/%s/tags/%s' % (
+ self.uri_prefix, resource_type, resource_id, tag)
+ resp, _ = self.put(uri, json.dumps({}))
+ self.expected_success(201, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def check_tag_existence(self, resource_type, resource_id, tag):
+ """Confirm that a given tag is set on the resource.
+
+ For more information, please refer to the official API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#confirm-a-tag
+ """
+ # TODO(felipemonteiro): Use the "check_resource" method in
+ # ``BaseNetworkClient`` once it has been implemented.
+ uri = '%s/%s/%s/tags/%s' % (
+ self.uri_prefix, resource_type, resource_id, tag)
+ resp, _ = self.get(uri)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def update_all_tags(self, resource_type, resource_id, tags):
+ """Replace all tags on the resource.
+
+ For more information, please refer to the official API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#replace-all-tags
+ """
+ uri = '/%s/%s/tags' % (resource_type, resource_id)
+ put_body = {"tags": tags}
+ return self.update_resource(uri, put_body)
+
+ def delete_tag(self, resource_type, resource_id, tag):
+ """Removes a tag on the resource.
+
+ For more information, please refer to the official API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#remove-a-tag
+ """
+ uri = '/%s/%s/tags/%s' % (resource_type, resource_id, tag)
+ return self.delete_resource(uri)
+
+ def delete_all_tags(self, resource_type, resource_id):
+ """Removes all tags on the resource.
+
+ For more information, please refer to the official API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#remove-all-tags
+ """
+ uri = '/%s/%s/tags' % (resource_type, resource_id)
+ return self.delete_resource(uri)
+
+ def list_tags(self, resource_type, resource_id):
+ """Retrieves the tags for a resource.
+
+ For more information, please refer to the official API reference:
+ http://developer.openstack.org/api-ref/networking/v2/index.html#obtain-tag-list
+ """
+ uri = '/%s/%s/tags' % (resource_type, resource_id)
+ return self.list_resources(uri)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index f25ab1d..38e03c7 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -313,13 +313,15 @@
return secgroup
- def get_remote_client(self, ip_address, username=None, private_key=None):
+ def get_remote_client(self, ip_address, username=None, private_key=None,
+ server=None):
"""Get a SSH client to a remote server
@param ip_address the server floating or fixed IP address to use
for ssh validation
@param username name of the Linux account on the remote server
@param private_key the SSH private key to use
+ @param server: server dict, used for debugging purposes
@return a RemoteClient object
"""
@@ -334,22 +336,10 @@
else:
password = CONF.validation.image_ssh_password
private_key = None
- linux_client = remote_client.RemoteClient(ip_address, username,
- pkey=private_key,
- password=password)
- try:
- linux_client.validate_authentication()
- except Exception as e:
- message = ('Initializing SSH connection to %(ip)s failed. '
- 'Error: %(error)s' % {'ip': ip_address,
- 'error': e})
- caller = test_utils.find_test_caller()
- if caller:
- message = '(%s) %s' % (caller, message)
- LOG.exception(message)
- self._log_console_output()
- raise
-
+ linux_client = remote_client.RemoteClient(
+ ip_address, username, pkey=private_key, password=password,
+ server=server, servers_client=self.servers_client)
+ linux_client.validate_authentication()
return linux_client
def _image_create(self, name, fmt, path,
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index eae1056..26a834b 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -141,14 +141,16 @@
# check that we can SSH to the server before reboot
self.linux_client = self.get_remote_client(
- floating_ip['ip'], private_key=keypair['private_key'])
+ floating_ip['ip'], private_key=keypair['private_key'],
+ server=server)
self.nova_reboot(server)
# check that we can SSH to the server after reboot
# (both connections are part of the scenario)
self.linux_client = self.get_remote_client(
- floating_ip['ip'], private_key=keypair['private_key'])
+ floating_ip['ip'], private_key=keypair['private_key'],
+ server=server)
self.check_disks()
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 4efeffd..48ddac6 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -240,7 +240,7 @@
ip_address = old_floating_ip['floating_ip_address']
private_key = self._get_server_key(server)
ssh_client = self.get_remote_client(
- ip_address, private_key=private_key)
+ ip_address, private_key=private_key, server=server)
old_nic_list = self._get_server_nics(ssh_client)
# get a port from a list of one item
port_list = self.os_admin.ports_client.list_ports(
@@ -348,7 +348,8 @@
ip_address = floating_ip['floating_ip_address']
private_key = self._get_server_key(self.floating_ip_tuple.server)
ssh_source = self.get_remote_client(
- ip_address, private_key=private_key)
+ ip_address, private_key=private_key,
+ server=self.floating_ip_tuple.server)
for remote_ip in address_list:
self.check_remote_connectivity(ssh_source, remote_ip,
@@ -575,7 +576,7 @@
ip_address = floating_ip['floating_ip_address']
private_key = self._get_server_key(server)
ssh_client = self.get_remote_client(
- ip_address, private_key=private_key)
+ ip_address, private_key=private_key, server=server)
dns_servers = [initial_dns_server]
servers = ssh_client.get_dns_servers()
@@ -641,7 +642,8 @@
private_key = self._get_server_key(server2)
ssh_client = self.get_remote_client(server2_fip['floating_ip_address'],
- private_key=private_key)
+ private_key=private_key,
+ server=server2)
self.check_public_network_connectivity(
should_connect=True, msg="before updating "
@@ -830,7 +832,8 @@
spoof_port = new_ports[0]
private_key = self._get_server_key(server)
ssh_client = self.get_remote_client(fip['floating_ip_address'],
- private_key=private_key)
+ private_key=private_key,
+ server=server)
spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
peer = self._create_server(self.new_net)
peer_address = peer['addresses'][self.new_net['name']][0]['addr']
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 6d9addd..bf26c2e 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -131,7 +131,7 @@
ips = self.define_server_ips(srv=srv)
ssh = self.get_remote_client(
ip_address=fip['floating_ip_address'],
- username=username)
+ username=username, server=srv)
return ssh, ips, srv["id"]
def turn_nic6_on(self, ssh, sid, network_id):
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 77563b3..0c441ab 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -62,7 +62,8 @@
self.ssh_client = self.get_remote_client(
ip_address=self.fip,
username=self.ssh_user,
- private_key=keypair['private_key'])
+ private_key=keypair['private_key'],
+ server=self.instance)
def verify_metadata(self):
if self.run_ssh and CONF.compute_feature_enabled.metadata_service:
diff --git a/tempest/scenario/test_volume_migrate_attached.py b/tempest/scenario/test_volume_migrate_attached.py
index 63dc23d..81b71b1 100644
--- a/tempest/scenario/test_volume_migrate_attached.py
+++ b/tempest/scenario/test_volume_migrate_attached.py
@@ -41,6 +41,7 @@
def setup_clients(cls):
super(TestVolumeMigrateRetypeAttached, cls).setup_clients()
cls.admin_volume_types_client = cls.os_admin.volume_types_v2_client
+ cls.admin_volumes_client = cls.os_admin.volumes_v2_client
@classmethod
def skip_checks(cls):
@@ -82,7 +83,7 @@
def _volume_retype_with_migration(self, volume_id, new_volume_type):
migration_policy = 'on-demand'
- self.volumes_client.retype_volume(
+ self.admin_volumes_client.retype_volume(
volume_id, new_type=new_volume_type,
migration_policy=migration_policy)
waiters.wait_for_volume_retype(self.volumes_client,
diff --git a/tempest/tests/lib/services/identity/v2/test_identity_client.py b/tempest/tests/lib/services/identity/v2/test_identity_client.py
index 96d50d7..303d1f7 100644
--- a/tempest/tests/lib/services/identity/v2/test_identity_client.py
+++ b/tempest/tests/lib/services/identity/v2/test_identity_client.py
@@ -26,6 +26,33 @@
}
}
+ FAKE_ENDPOINTS_FOR_TOKEN = {
+ "endpoints_links": [],
+ "endpoints": [
+ {
+ "name": "nova",
+ "adminURL": "https://nova.region-one.internal.com/" +
+ "v2/be1319401cfa4a0aa590b97cc7b64d8d",
+ "region": "RegionOne",
+ "internalURL": "https://nova.region-one.internal.com/" +
+ "v2/be1319401cfa4a0aa590b97cc7b64d8d",
+ "type": "compute",
+ "id": "11b41ee1b00841128b7333d4bf1a6140",
+ "publicURL": "https://nova.region-one.public.com/v2/" +
+ "be1319401cfa4a0aa590b97cc7b64d8d"
+ },
+ {
+ "name": "neutron",
+ "adminURL": "https://neutron.region-one.internal.com/",
+ "region": "RegionOne",
+ "internalURL": "https://neutron.region-one.internal.com/",
+ "type": "network",
+ "id": "cdbfa3c416d741a9b5c968f2dc628acb",
+ "publicURL": "https://neutron.region-one.public.com/"
+ }
+ ]
+ }
+
FAKE_API_INFO = {
"name": "API_info",
"type": "API",
@@ -148,6 +175,22 @@
bytes_body,
token_id="cbc36478b0bd8e67e89")
+ def _test_list_endpoints_for_token(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_endpoints_for_token,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_ENDPOINTS_FOR_TOKEN,
+ bytes_body,
+ token_id="cbc36478b0bd8e67e89")
+
+ def _test_check_token_existence(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.check_token_existence,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ bytes_body,
+ token_id="cbc36478b0bd8e67e89")
+
def test_show_api_description_with_str_body(self):
self._test_show_api_description()
@@ -166,6 +209,18 @@
def test_show_token_with_bytes_body(self):
self._test_show_token(bytes_body=True)
+ def test_list_endpoints_for_token_with_str_body(self):
+ self._test_list_endpoints_for_token()
+
+ def test_list_endpoints_for_token_with_bytes_body(self):
+ self._test_list_endpoints_for_token(bytes_body=True)
+
+ def test_check_token_existence_with_bytes_body(self):
+ self._test_check_token_existence(bytes_body=True)
+
+ def test_check_token_existence_with_str_body(self):
+ self._test_check_token_existence()
+
def test_delete_token(self):
self.check_service_client_function(
self.client.delete_token,
diff --git a/tempest/tests/lib/services/identity/v3/test_endpoint_groups_client.py b/tempest/tests/lib/services/identity/v3/test_endpoint_groups_client.py
new file mode 100644
index 0000000..8b034e6
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_endpoint_groups_client.py
@@ -0,0 +1,162 @@
+# Copyright 2017 AT&T Corporation.
+# 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 endpoint_groups_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestEndPointGroupsClient(base.BaseServiceTest):
+ FAKE_CREATE_ENDPOINT_GROUP = {
+ "endpoint_group": {
+ "id": 1,
+ "name": "FAKE_ENDPOINT_GROUP",
+ "description": "FAKE SERVICE ENDPOINT GROUP",
+ "filters": {
+ "service_id": 1
+ }
+ }
+ }
+
+ FAKE_ENDPOINT_GROUP_INFO = {
+ "endpoint_group": {
+ "id": 1,
+ "name": "FAKE_ENDPOINT_GROUP",
+ "description": "FAKE SERVICE ENDPOINT GROUP",
+ "links": {
+ "self": "http://example.com/identity/v3/OS-EP-FILTER/" +
+ "endpoint_groups/1"
+ },
+ "filters": {
+ "service_id": 1
+ }
+ }
+ }
+
+ FAKE_LIST_ENDPOINT_GROUPS = {
+ "endpoint_groups": [
+ {
+ "id": 1,
+ "name": "SERVICE_GROUP1",
+ "description": "FAKE SERVICE ENDPOINT GROUP",
+ "links": {
+ "self": "http://example.com/identity/v3/OS-EP-FILTER/" +
+ "endpoint_groups/1"
+ },
+ "filters": {
+ "service_id": 1
+ }
+ },
+ {
+ "id": 2,
+ "name": "SERVICE_GROUP2",
+ "description": "FAKE SERVICE ENDPOINT GROUP",
+ "links": {
+ "self": "http://example.com/identity/v3/OS-EP-FILTER/" +
+ "endpoint_groups/2"
+ },
+ "filters": {
+ "service_id": 2
+ }
+ }
+ ]
+ }
+
+ def setUp(self):
+ super(TestEndPointGroupsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = endpoint_groups_client.EndPointGroupsClient(
+ fake_auth, 'identity', 'regionOne')
+
+ def _test_create_endpoint_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_endpoint_group,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_CREATE_ENDPOINT_GROUP,
+ bytes_body,
+ status=201,
+ name="FAKE_ENDPOINT_GROUP",
+ filters={'service_id': "1"})
+
+ def _test_show_endpoint_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_endpoint_group,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_ENDPOINT_GROUP_INFO,
+ bytes_body,
+ endpoint_group_id="1")
+
+ def _test_check_endpoint_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.check_endpoint_group,
+ 'tempest.lib.common.rest_client.RestClient.head',
+ {},
+ bytes_body,
+ status=200,
+ endpoint_group_id="1")
+
+ def _test_update_endpoint_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_endpoint_group,
+ 'tempest.lib.common.rest_client.RestClient.patch',
+ self.FAKE_ENDPOINT_GROUP_INFO,
+ bytes_body,
+ endpoint_group_id="1",
+ name="NewName")
+
+ def _test_list_endpoint_groups(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_endpoint_groups,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_ENDPOINT_GROUPS,
+ bytes_body)
+
+ def test_create_endpoint_group_with_str_body(self):
+ self._test_create_endpoint_group()
+
+ def test_create_endpoint_group_with_bytes_body(self):
+ self._test_create_endpoint_group(bytes_body=True)
+
+ def test_show_endpoint_group_with_str_body(self):
+ self._test_show_endpoint_group()
+
+ def test_show_endpoint_group_with_bytes_body(self):
+ self._test_show_endpoint_group(bytes_body=True)
+
+ def test_check_endpoint_group_with_str_body(self):
+ self._test_check_endpoint_group()
+
+ def test_check_endpoint_group_with_bytes_body(self):
+ self._test_check_endpoint_group(bytes_body=True)
+
+ def test_list_endpoint_groups_with_str_body(self):
+ self._test_list_endpoint_groups()
+
+ def test_list_endpoint_groups_with_bytes_body(self):
+ self._test_list_endpoint_groups(bytes_body=True)
+
+ def test_update_endpoint_group_with_str_body(self):
+ self._test_update_endpoint_group()
+
+ def test_update_endpoint_group_with_bytes_body(self):
+ self._test_update_endpoint_group(bytes_body=True)
+
+ def test_delete_endpoint_group(self):
+ self.check_service_client_function(
+ self.client.delete_endpoint_group,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ endpoint_group_id="1",
+ status=204)
diff --git a/tempest/tests/lib/services/network/test_extensions_client.py b/tempest/tests/lib/services/network/test_extensions_client.py
new file mode 100644
index 0000000..27eb485
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_extensions_client.py
@@ -0,0 +1,201 @@
+# Copyright 2017 AT&T Corporation.
+# 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.network import extensions_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestExtensionsClient(base.BaseServiceTest):
+
+ FAKE_EXTENSIONS = {
+ "extensions": [
+ {
+ "updated": "2013-01-20T00:00:00-00:00",
+ "name": "Neutron Service Type Management",
+ "links": [],
+ "alias": "service-type",
+ "description": "API for retrieving service providers for"
+ " Neutron advanced services"
+ },
+ {
+ "updated": "2012-10-05T10:00:00-00:00",
+ "name": "security-group",
+ "links": [],
+ "alias": "security-group",
+ "description": "The security groups extension."
+ },
+ {
+ "updated": "2013-02-07T10:00:00-00:00",
+ "name": "L3 Agent Scheduler",
+ "links": [],
+ "alias": "l3_agent_scheduler",
+ "description": "Schedule routers among l3 agents"
+ },
+ {
+ "updated": "2013-02-07T10:00:00-00:00",
+ "name": "Loadbalancer Agent Scheduler",
+ "links": [],
+ "alias": "lbaas_agent_scheduler",
+ "description": "Schedule pools among lbaas agents"
+ },
+ {
+ "updated": "2013-03-28T10:00:00-00:00",
+ "name": "Neutron L3 Configurable external gateway mode",
+ "links": [],
+ "alias": "ext-gw-mode",
+ "description":
+ "Extension of the router abstraction for specifying whether"
+ " SNAT should occur on the external gateway"
+ },
+ {
+ "updated": "2014-02-03T10:00:00-00:00",
+ "name": "Port Binding",
+ "links": [],
+ "alias": "binding",
+ "description": "Expose port bindings of a virtual port to"
+ " external application"
+ },
+ {
+ "updated": "2012-09-07T10:00:00-00:00",
+ "name": "Provider Network",
+ "links": [],
+ "alias": "provider",
+ "description": "Expose mapping of virtual networks to"
+ " physical networks"
+ },
+ {
+ "updated": "2013-02-03T10:00:00-00:00",
+ "name": "agent",
+ "links": [],
+ "alias": "agent",
+ "description": "The agent management extension."
+ },
+ {
+ "updated": "2012-07-29T10:00:00-00:00",
+ "name": "Quota management support",
+ "links": [],
+ "alias": "quotas",
+ "description": "Expose functions for quotas management per"
+ " tenant"
+ },
+ {
+ "updated": "2013-02-07T10:00:00-00:00",
+ "name": "DHCP Agent Scheduler",
+ "links": [],
+ "alias": "dhcp_agent_scheduler",
+ "description": "Schedule networks among dhcp agents"
+ },
+ {
+ "updated": "2013-06-27T10:00:00-00:00",
+ "name": "Multi Provider Network",
+ "links": [],
+ "alias": "multi-provider",
+ "description": "Expose mapping of virtual networks to"
+ " multiple physical networks"
+ },
+ {
+ "updated": "2013-01-14T10:00:00-00:00",
+ "name": "Neutron external network",
+ "links": [],
+ "alias": "external-net",
+ "description": "Adds external network attribute to network"
+ " resource."
+ },
+ {
+ "updated": "2012-07-20T10:00:00-00:00",
+ "name": "Neutron L3 Router",
+ "links": [],
+ "alias": "router",
+ "description": "Router abstraction for basic L3 forwarding"
+ " between L2 Neutron networks and access to external"
+ " networks via a NAT gateway."
+ },
+ {
+ "updated": "2013-07-23T10:00:00-00:00",
+ "name": "Allowed Address Pairs",
+ "links": [],
+ "alias": "allowed-address-pairs",
+ "description": "Provides allowed address pairs"
+ },
+ {
+ "updated": "2013-03-17T12:00:00-00:00",
+ "name": "Neutron Extra DHCP opts",
+ "links": [],
+ "alias": "extra_dhcp_opt",
+ "description": "Extra options configuration for DHCP. For"
+ " example PXE boot options to DHCP clients can be specified"
+ " (e.g. tftp-server, server-ip-address, bootfile-name)"
+ },
+ {
+ "updated": "2012-10-07T10:00:00-00:00",
+ "name": "LoadBalancing service",
+ "links": [],
+ "alias": "lbaas",
+ "description": "Extension for LoadBalancing service"
+ },
+ {
+ "updated": "2013-02-01T10:00:00-00:00",
+ "name": "Neutron Extra Route",
+ "links": [],
+ "alias": "extraroute",
+ "description": "Extra routes configuration for L3 router"
+ },
+ {
+ "updated": "2016-01-24T10:00:00-00:00",
+ "name": "Neutron Port Data Plane Status",
+ "links": [],
+ "alias": "data-plane-status",
+ "description": "Status of the underlying data plane."
+ }
+ ]
+ }
+
+ FAKE_EXTENSION_ALIAS = "service-type"
+
+ def setUp(self):
+ super(TestExtensionsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.extensions_client = extensions_client.ExtensionsClient(
+ fake_auth, "network", "regionOne")
+
+ def _test_list_extensions(self, bytes_body=False):
+ self.check_service_client_function(
+ self.extensions_client.list_extensions,
+ "tempest.lib.common.rest_client.RestClient.get",
+ self.FAKE_EXTENSIONS,
+ bytes_body,
+ 200)
+
+ def _test_show_extension(self, bytes_body=False):
+ self.check_service_client_function(
+ self.extensions_client.show_extension,
+ "tempest.lib.common.rest_client.RestClient.get",
+ {"extension": self.FAKE_EXTENSIONS["extensions"][0]},
+ bytes_body,
+ 200,
+ ext_alias=self.FAKE_EXTENSION_ALIAS)
+
+ def test_list_extensions_with_str_body(self):
+ self._test_list_extensions()
+
+ def test_list_extensions_with_bytes_body(self):
+ self._test_list_extensions(bytes_body=True)
+
+ def test_show_extension_with_str_body(self):
+ self._test_show_extension()
+
+ def test_show_extension_with_bytes_body(self):
+ self._test_show_extension(bytes_body=True)
diff --git a/tempest/tests/lib/services/network/test_floating_ips_client.py b/tempest/tests/lib/services/network/test_floating_ips_client.py
new file mode 100644
index 0000000..c5b1845
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_floating_ips_client.py
@@ -0,0 +1,145 @@
+# Copyright 2017 AT&T Corporation.
+# 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.
+
+import copy
+
+from tempest.lib.services.network import floating_ips_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestFloatingIPsClient(base.BaseServiceTest):
+
+ FAKE_FLOATING_IPS = {
+ "floatingips": [
+ {
+ "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f",
+ "description": "for test",
+ "created_at": "2016-12-21T10:55:50Z",
+ "updated_at": "2016-12-21T10:55:53Z",
+ "revision_number": 1,
+ "project_id": "4969c491a3c74ee4af974e6d800c62de",
+ "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+ "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+ "fixed_ip_address": "10.0.0.3",
+ "floating_ip_address": "172.24.4.228",
+ "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab",
+ "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7",
+ "status": "ACTIVE"
+ },
+ {
+ "router_id": None,
+ "description": "for test",
+ "created_at": "2016-12-21T11:55:50Z",
+ "updated_at": "2016-12-21T11:55:53Z",
+ "revision_number": 2,
+ "project_id": "4969c491a3c74ee4af974e6d800c62de",
+ "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+ "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+ "fixed_ip_address": None,
+ "floating_ip_address": "172.24.4.227",
+ "port_id": None,
+ "id": "61cea855-49cb-4846-997d-801b70c71bdd",
+ "status": "DOWN"
+ }
+ ]
+ }
+
+ FAKE_FLOATING_IP_ID = "2f245a7b-796b-4f26-9cf9-9e82d248fda7"
+
+ def setUp(self):
+ super(TestFloatingIPsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.floating_ips_client = floating_ips_client.FloatingIPsClient(
+ fake_auth, "compute", "regionOne")
+
+ def _test_list_floatingips(self, bytes_body=False):
+ self.check_service_client_function(
+ self.floating_ips_client.list_floatingips,
+ "tempest.lib.common.rest_client.RestClient.get",
+ self.FAKE_FLOATING_IPS,
+ bytes_body,
+ 200)
+
+ def _test_create_floatingip(self, bytes_body=False):
+ self.check_service_client_function(
+ self.floating_ips_client.create_floatingip,
+ "tempest.lib.common.rest_client.RestClient.post",
+ {"floatingip": self.FAKE_FLOATING_IPS["floatingips"][1]},
+ bytes_body,
+ 201,
+ floating_network_id="172.24.4.228")
+
+ def _test_show_floatingip(self, bytes_body=False):
+ self.check_service_client_function(
+ self.floating_ips_client.show_floatingip,
+ "tempest.lib.common.rest_client.RestClient.get",
+ {"floatingip": self.FAKE_FLOATING_IPS["floatingips"][0]},
+ bytes_body,
+ 200,
+ floatingip_id=self.FAKE_FLOATING_IP_ID)
+
+ def _test_update_floatingip(self, bytes_body=False):
+ update_kwargs = {
+ "port_id": "fc861431-0e6c-4842-a0ed-e2363f9bc3a8"
+ }
+
+ resp_body = {
+ "floatingip": copy.deepcopy(
+ self.FAKE_FLOATING_IPS["floatingips"][0]
+ )
+ }
+ resp_body["floatingip"].update(update_kwargs)
+
+ self.check_service_client_function(
+ self.floating_ips_client.update_floatingip,
+ "tempest.lib.common.rest_client.RestClient.put",
+ resp_body,
+ bytes_body,
+ 200,
+ floatingip_id=self.FAKE_FLOATING_IP_ID,
+ **update_kwargs)
+
+ def test_list_floatingips_with_str_body(self):
+ self._test_list_floatingips()
+
+ def test_list_floatingips_with_bytes_body(self):
+ self._test_list_floatingips(bytes_body=True)
+
+ def test_create_floatingip_with_str_body(self):
+ self._test_create_floatingip()
+
+ def test_create_floatingip_with_bytes_body(self):
+ self._test_create_floatingip(bytes_body=True)
+
+ def test_show_floatingips_with_str_body(self):
+ self._test_show_floatingip()
+
+ def test_show_floatingips_with_bytes_body(self):
+ self._test_show_floatingip(bytes_body=True)
+
+ def test_update_floatingip_with_str_body(self):
+ self._test_update_floatingip()
+
+ def test_update_floatingip_with_bytes_body(self):
+ self._test_update_floatingip(bytes_body=True)
+
+ def test_delete_floatingip(self):
+ self.check_service_client_function(
+ self.floating_ips_client.delete_floatingip,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ status=204,
+ floatingip_id=self.FAKE_FLOATING_IP_ID)
diff --git a/tempest/tests/lib/services/network/test_metering_label_rules_client.py b/tempest/tests/lib/services/network/test_metering_label_rules_client.py
new file mode 100644
index 0000000..047c34f
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_metering_label_rules_client.py
@@ -0,0 +1,110 @@
+# Copyright 2017 AT&T Corporation.
+# 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.network import metering_label_rules_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestMeteringLabelRulesClient(base.BaseServiceTest):
+
+ FAKE_METERING_LABEL_RULES = {
+ "metering_label_rules": [
+ {
+ "remote_ip_prefix": "20.0.0.0/24",
+ "direction": "ingress",
+ "metering_label_id": "e131d186-b02d-4c0b-83d5-0c0725c4f812",
+ "id": "9536641a-7d14-4dc5-afaf-93a973ce0eb8",
+ "excluded": False
+ },
+ {
+ "remote_ip_prefix": "10.0.0.0/24",
+ "direction": "ingress",
+ "metering_label_id": "e131d186-b02d-4c0b-83d5-0c0725c4f812",
+ "id": "ffc6fd15-40de-4e7d-b617-34d3f7a93aec",
+ "excluded": False
+ }
+ ]
+ }
+
+ FAKE_METERING_LABEL_RULE = {
+ "remote_ip_prefix": "20.0.0.0/24",
+ "direction": "ingress",
+ "metering_label_id": "e131d186-b02d-4c0b-83d5-0c0725c4f812"
+ }
+
+ FAKE_METERING_LABEL_ID = "e131d186-b02d-4c0b-83d5-0c0725c4f812"
+ FAKE_METERING_LABEL_RULE_ID = "9536641a-7d14-4dc5-afaf-93a973ce0eb8"
+
+ def setUp(self):
+ super(TestMeteringLabelRulesClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.metering_label_rules_client = \
+ metering_label_rules_client.MeteringLabelRulesClient(
+ fake_auth, "network", "regionOne")
+
+ def _test_list_metering_label_rules(self, bytes_body=False):
+ self.check_service_client_function(
+ self.metering_label_rules_client.list_metering_label_rules,
+ "tempest.lib.common.rest_client.RestClient.get",
+ self.FAKE_METERING_LABEL_RULES,
+ bytes_body,
+ 200)
+
+ def _test_create_metering_label_rule(self, bytes_body=False):
+ self.check_service_client_function(
+ self.metering_label_rules_client.create_metering_label_rule,
+ "tempest.lib.common.rest_client.RestClient.post",
+ {"metering_label_rule": self.FAKE_METERING_LABEL_RULES[
+ "metering_label_rules"][0]},
+ bytes_body,
+ 201,
+ **self.FAKE_METERING_LABEL_RULE)
+
+ def _test_show_metering_label_rule(self, bytes_body=False):
+ self.check_service_client_function(
+ self.metering_label_rules_client.show_metering_label_rule,
+ "tempest.lib.common.rest_client.RestClient.get",
+ {"metering_label_rule": self.FAKE_METERING_LABEL_RULES[
+ "metering_label_rules"][0]},
+ bytes_body,
+ 200,
+ metering_label_rule_id=self.FAKE_METERING_LABEL_RULE_ID)
+
+ def test_delete_metering_label_rule(self):
+ self.check_service_client_function(
+ self.metering_label_rules_client.delete_metering_label_rule,
+ "tempest.lib.common.rest_client.RestClient.delete",
+ {},
+ status=204,
+ metering_label_rule_id=self.FAKE_METERING_LABEL_RULE_ID)
+
+ def test_list_metering_label_rules_with_str_body(self):
+ self._test_list_metering_label_rules()
+
+ def test_list_metering_label_rules_with_bytes_body(self):
+ self._test_list_metering_label_rules(bytes_body=True)
+
+ def test_create_metering_label_rule_with_str_body(self):
+ self._test_create_metering_label_rule()
+
+ def test_create_metering_label_rule_with_bytes_body(self):
+ self._test_create_metering_label_rule(bytes_body=True)
+
+ def test_show_metering_label_rule_with_str_body(self):
+ self._test_show_metering_label_rule()
+
+ def test_show_metering_label_rule_with_bytes_body(self):
+ self._test_show_metering_label_rule(bytes_body=True)
diff --git a/tempest/tests/lib/services/network/test_metering_labels_client.py b/tempest/tests/lib/services/network/test_metering_labels_client.py
new file mode 100644
index 0000000..a048326
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_metering_labels_client.py
@@ -0,0 +1,107 @@
+# Copyright 2017 AT&T Corporation.
+# 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.network import metering_labels_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestMeteringLabelsClient(base.BaseServiceTest):
+
+ FAKE_METERING_LABELS = {
+ "metering_labels": [
+ {
+ "project_id": "45345b0ee1ea477fac0f541b2cb79cd4",
+ "tenant_id": "45345b0ee1ea477fac0f541b2cb79cd4",
+ "description": "label1 description",
+ "name": "label1",
+ "id": "a6700594-5b7a-4105-8bfe-723b346ce866",
+ "shared": False
+ },
+ {
+ "project_id": "45345b0ee1ea477fac0f541b2cb79cd4",
+ "tenant_id": "45345b0ee1ea477fac0f541b2cb79cd4",
+ "description": "label2 description",
+ "name": "label2",
+ "id": "e131d186-b02d-4c0b-83d5-0c0725c4f812",
+ "shared": False
+ }
+ ]
+ }
+
+ FAKE_METERING_LABEL_ID = "a6700594-5b7a-4105-8bfe-723b346ce866"
+
+ def setUp(self):
+ super(TestMeteringLabelsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.metering_labels_client = \
+ metering_labels_client.MeteringLabelsClient(
+ fake_auth, "network", "regionOne")
+
+ def _test_list_metering_labels(self, bytes_body=False):
+ self.check_service_client_function(
+ self.metering_labels_client.list_metering_labels,
+ "tempest.lib.common.rest_client.RestClient.get",
+ self.FAKE_METERING_LABELS,
+ bytes_body,
+ 200)
+
+ def _test_create_metering_label(self, bytes_body=False):
+ self.check_service_client_function(
+ self.metering_labels_client.create_metering_label,
+ "tempest.lib.common.rest_client.RestClient.post",
+ {"metering_label": self.FAKE_METERING_LABELS[
+ "metering_labels"][1]},
+ bytes_body,
+ 201,
+ name="label1",
+ description="label1 description",
+ shared=False)
+
+ def _test_show_metering_label(self, bytes_body=False):
+ self.check_service_client_function(
+ self.metering_labels_client.show_metering_label,
+ "tempest.lib.common.rest_client.RestClient.get",
+ {"metering_label": self.FAKE_METERING_LABELS[
+ "metering_labels"][0]},
+ bytes_body,
+ 200,
+ metering_label_id=self.FAKE_METERING_LABEL_ID)
+
+ def test_delete_metering_label(self):
+ self.check_service_client_function(
+ self.metering_labels_client.delete_metering_label,
+ "tempest.lib.common.rest_client.RestClient.delete",
+ {},
+ status=204,
+ metering_label_id=self.FAKE_METERING_LABEL_ID)
+
+ def test_list_metering_labels_with_str_body(self):
+ self._test_list_metering_labels()
+
+ def test_list_metering_labels_with_bytes_body(self):
+ self._test_list_metering_labels(bytes_body=True)
+
+ def test_create_metering_label_with_str_body(self):
+ self._test_create_metering_label()
+
+ def test_create_metering_label_with_bytes_body(self):
+ self._test_create_metering_label(bytes_body=True)
+
+ def test_show_metering_label_with_str_body(self):
+ self._test_show_metering_label()
+
+ def test_show_metering_label_with_bytes_body(self):
+ self._test_show_metering_label(bytes_body=True)
diff --git a/tempest/tests/lib/services/network/test_ports_client.py b/tempest/tests/lib/services/network/test_ports_client.py
new file mode 100644
index 0000000..20ef3f1
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_ports_client.py
@@ -0,0 +1,198 @@
+# Copyright 2017 AT&T Corporation.
+# 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.
+
+import copy
+
+from tempest.lib.services.network import ports_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestPortsClient(base.BaseServiceTest):
+
+ FAKE_PORTS = {
+ "ports": [
+ {
+ "admin_state_up": True,
+ "allowed_address_pairs": [],
+ "data_plane_status": None,
+ "description": "",
+ "device_id": "9ae135f4-b6e0-4dad-9e91-3c223e385824",
+ "device_owner": "network:router_gateway",
+ "extra_dhcp_opts": [],
+ "fixed_ips": [
+ {
+ "ip_address": "172.24.4.2",
+ "subnet_id": "008ba151-0b8c-4a67-98b5-0d2b87666062"
+ }
+ ],
+ "id": "d80b1a3b-4fc1-49f3-952e-1e2ab7081d8b",
+ "mac_address": "fa:16:3e:58:42:ed",
+ "name": "",
+ "network_id": "70c1db1f-b701-45bd-96e0-a313ee3430b3",
+ "project_id": "",
+ "security_groups": [],
+ "status": "ACTIVE",
+ "tenant_id": ""
+ },
+ {
+ "admin_state_up": True,
+ "allowed_address_pairs": [],
+ "data_plane_status": None,
+ "description": "",
+ "device_id": "9ae135f4-b6e0-4dad-9e91-3c223e385824",
+ "device_owner": "network:router_interface",
+ "extra_dhcp_opts": [],
+ "fixed_ips": [
+ {
+ "ip_address": "10.0.0.1",
+ "subnet_id": "288bf4a1-51ba-43b6-9d0a-520e9005db17"
+ }
+ ],
+ "id": "f71a6703-d6de-4be1-a91a-a570ede1d159",
+ "mac_address": "fa:16:3e:bb:3c:e4",
+ "name": "",
+ "network_id": "f27aa545-cbdd-4907-b0c6-c9e8b039dcc2",
+ "project_id": "d397de8a63f341818f198abb0966f6f3",
+ "security_groups": [],
+ "status": "ACTIVE",
+ "tenant_id": "d397de8a63f341818f198abb0966f6f3"
+ }
+ ]
+ }
+
+ FAKE_PORT_ID = "d80b1a3b-4fc1-49f3-952e-1e2ab7081d8b"
+
+ FAKE_PORT1 = {
+ "admin_state_up": True,
+ "name": "",
+ "network_id": "70c1db1f-b701-45bd-96e0-a313ee3430b3"
+ }
+
+ FAKE_PORT2 = {
+ "admin_state_up": True,
+ "name": "",
+ "network_id": "f27aa545-cbdd-4907-b0c6-c9e8b039dcc2"
+ }
+
+ FAKE_PORTS_REQ = {
+ "ports": [
+ FAKE_PORT1,
+ FAKE_PORT2
+ ]
+ }
+
+ def setUp(self):
+ super(TestPortsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.ports_client = ports_client.PortsClient(
+ fake_auth, "network", "regionOne")
+
+ def _test_list_ports(self, bytes_body=False):
+ self.check_service_client_function(
+ self.ports_client.list_ports,
+ "tempest.lib.common.rest_client.RestClient.get",
+ self.FAKE_PORTS,
+ bytes_body,
+ 200)
+
+ def _test_create_port(self, bytes_body=False):
+ self.check_service_client_function(
+ self.ports_client.create_port,
+ "tempest.lib.common.rest_client.RestClient.post",
+ {"port": self.FAKE_PORTS["ports"][0]},
+ bytes_body,
+ 201,
+ **self.FAKE_PORT1)
+
+ def _test_create_bulk_ports(self, bytes_body=False):
+ self.check_service_client_function(
+ self.ports_client.create_bulk_ports,
+ "tempest.lib.common.rest_client.RestClient.post",
+ self.FAKE_PORTS,
+ bytes_body,
+ 201,
+ ports=self.FAKE_PORTS_REQ)
+
+ def _test_show_port(self, bytes_body=False):
+ self.check_service_client_function(
+ self.ports_client.show_port,
+ "tempest.lib.common.rest_client.RestClient.get",
+ {"port": self.FAKE_PORTS["ports"][0]},
+ bytes_body,
+ 200,
+ port_id=self.FAKE_PORT_ID)
+
+ def _test_update_port(self, bytes_body=False):
+ update_kwargs = {
+ "admin_state_up": True,
+ "device_id": "d90a13da-be41-461f-9f99-1dbcf438fdf2",
+ "device_owner": "compute:nova",
+ "name": "test-for-port-update"
+ }
+
+ resp_body = {
+ "port": copy.deepcopy(
+ self.FAKE_PORTS["ports"][0]
+ )
+ }
+ resp_body["port"].update(update_kwargs)
+
+ self.check_service_client_function(
+ self.ports_client.update_port,
+ "tempest.lib.common.rest_client.RestClient.put",
+ resp_body,
+ bytes_body,
+ 200,
+ port_id=self.FAKE_PORT_ID,
+ **update_kwargs)
+
+ def test_delete_port(self):
+ self.check_service_client_function(
+ self.ports_client.delete_port,
+ "tempest.lib.common.rest_client.RestClient.delete",
+ {},
+ status=204,
+ port_id=self.FAKE_PORT_ID)
+
+ def test_list_ports_with_str_body(self):
+ self._test_list_ports()
+
+ def test_list_ports_with_bytes_body(self):
+ self._test_list_ports(bytes_body=True)
+
+ def test_create_port_with_str_body(self):
+ self._test_create_port()
+
+ def test_create_port_with_bytes_body(self):
+ self._test_create_port(bytes_body=True)
+
+ def test_create_bulk_port_with_str_body(self):
+ self._test_create_bulk_ports()
+
+ def test_create_bulk_port_with_bytes_body(self):
+ self._test_create_bulk_ports(bytes_body=True)
+
+ def test_show_port_with_str_body(self):
+ self._test_show_port()
+
+ def test_show_port_with_bytes_body(self):
+ self._test_show_port(bytes_body=True)
+
+ def test_update_port_with_str_body(self):
+ self._test_update_port()
+
+ def test_update_port_with_bytes_body(self):
+ self._test_update_port(bytes_body=True)
diff --git a/tempest/tests/lib/services/network/test_security_group_rules_client.py b/tempest/tests/lib/services/network/test_security_group_rules_client.py
new file mode 100644
index 0000000..ebffcbe
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_security_group_rules_client.py
@@ -0,0 +1,130 @@
+# Copyright 2017 AT&T Corporation.
+# 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.
+
+import copy
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.services.network import security_group_rules_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestSecurityGroupsClient(base.BaseServiceTest):
+
+ FAKE_SEC_GROUP_RULE_ID = "3c0e45ff-adaf-4124-b083-bf390e5482ff"
+
+ FAKE_SECURITY_GROUP_RULES = {
+ "security_group_rules": [
+ {
+ "direction": "egress",
+ "ethertype": "IPv6",
+ "id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
+ "port_range_max": None,
+ "port_range_min": None,
+ "protocol": None,
+ "remote_group_id": None,
+ "remote_ip_prefix": None,
+ "security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
+ "project_id": "e4f50856753b4dc6afee5fa6b9b6c550",
+ "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550",
+ "description": ""
+ },
+ {
+ "direction": "egress",
+ "ethertype": "IPv4",
+ "id": "93aa42e5-80db-4581-9391-3a608bd0e448",
+ "port_range_max": None,
+ "port_range_min": None,
+ "protocol": None,
+ "remote_group_id": None,
+ "remote_ip_prefix": None,
+ "security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
+ "project_id": "e4f50856753b4dc6afee5fa6b9b6c550",
+ "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550",
+ "description": ""
+ }
+ ]
+ }
+
+ FAKE_SECURITY_GROUP_RULE = copy.copy(
+ FAKE_SECURITY_GROUP_RULES['security_group_rules'][0])
+
+ def setUp(self):
+ super(TestSecurityGroupsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = security_group_rules_client.SecurityGroupRulesClient(
+ fake_auth, 'network', 'regionOne')
+
+ def _test_list_security_group_rules(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_security_group_rules,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_SECURITY_GROUP_RULES,
+ bytes_body,
+ mock_args='v2.0/security-group-rules')
+
+ def _test_create_security_group_rule(self, bytes_body=False):
+ kwargs = {'direction': 'egress',
+ 'security_group_id': '85cc3048-abc3-43cc-89b3-377341426ac5',
+ 'remote_ip_prefix': None}
+
+ self.check_service_client_function(
+ self.client.create_security_group_rule,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_SECURITY_GROUP_RULE,
+ bytes_body,
+ status=201,
+ mock_args=['v2.0/security-group-rules',
+ json.dumps({"security_group_rule": kwargs})],
+ **kwargs)
+
+ def _test_show_security_group_rule(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_security_group_rule,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_SECURITY_GROUP_RULE,
+ bytes_body,
+ security_group_rule_id=self.FAKE_SEC_GROUP_RULE_ID,
+ mock_args='v2.0/security-group-rules/%s'
+ % self.FAKE_SEC_GROUP_RULE_ID)
+
+ def test_list_security_group_rules_with_str_body(self):
+ self._test_list_security_group_rules()
+
+ def test_list_security_group_rules_with_bytes_body(self):
+ self._test_list_security_group_rules(bytes_body=True)
+
+ def test_create_security_group_rule_with_str_body(self):
+ self._test_create_security_group_rule()
+
+ def test_create_security_group_rule_with_bytes_body(self):
+ self._test_create_security_group_rule(bytes_body=True)
+
+ def test_show_security_group_rule_with_str_body(self):
+ self._test_show_security_group_rule()
+
+ def test_show_security_group_rule_with_bytes_body(self):
+ self._test_show_security_group_rule(bytes_body=True)
+
+ def test_delete_security_group_rule(self):
+ self.check_service_client_function(
+ self.client.delete_security_group_rule,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ status=204,
+ security_group_rule_id=self.FAKE_SEC_GROUP_RULE_ID,
+ mock_args='v2.0/security-group-rules/%s'
+ % self.FAKE_SEC_GROUP_RULE_ID)
diff --git a/tempest/tests/lib/services/network/test_security_groups_client.py b/tempest/tests/lib/services/network/test_security_groups_client.py
new file mode 100644
index 0000000..d066378
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_security_groups_client.py
@@ -0,0 +1,157 @@
+# Copyright 2017 AT&T Corporation.
+# 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.
+
+import copy
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.services.network import security_groups_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestSecurityGroupsClient(base.BaseServiceTest):
+
+ FAKE_SEC_GROUP_ID = "85cc3048-abc3-43cc-89b3-377341426ac5"
+
+ FAKE_SECURITY_GROUPS = {
+ "security_groups": [
+ {
+ "description": "default",
+ "id": FAKE_SEC_GROUP_ID,
+ "name": "fake-security-group-name",
+ "security_group_rules": [
+ {
+ "direction": "egress",
+ "ethertype": "IPv4",
+ "id": "38ce2d8e-e8f1-48bd-83c2-d33cb9f50c3d",
+ "port_range_max": None,
+ "port_range_min": None,
+ "protocol": None,
+ "remote_group_id": None,
+ "remote_ip_prefix": None,
+ "security_group_id": FAKE_SEC_GROUP_ID,
+ "project_id": "e4f50856753b4dc6afee5fa6b9b6c550",
+ "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550",
+ "description": ""
+ },
+ {
+ "direction": "egress",
+ "ethertype": "IPv6",
+ "id": "565b9502-12de-4ffd-91e9-68885cff6ae1",
+ "port_range_max": None,
+ "port_range_min": None,
+ "protocol": None,
+ "remote_group_id": None,
+ "remote_ip_prefix": None,
+ "security_group_id": FAKE_SEC_GROUP_ID,
+ "project_id": "e4f50856753b4dc6afee5fa6b9b6c550",
+ "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550",
+ "description": ""
+ }
+ ],
+ "project_id": "e4f50856753b4dc6afee5fa6b9b6c550",
+ "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
+ }
+ ]
+ }
+
+ FAKE_SECURITY_GROUP = {
+ "security_group": copy.deepcopy(
+ FAKE_SECURITY_GROUPS["security_groups"][0])
+ }
+
+ def setUp(self):
+ super(TestSecurityGroupsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = security_groups_client.SecurityGroupsClient(
+ fake_auth, 'network', 'regionOne')
+
+ def _test_list_security_groups(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_security_groups,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_SECURITY_GROUPS,
+ bytes_body,
+ mock_args='v2.0/security-groups')
+
+ def _test_create_security_group(self, bytes_body=False):
+ kwargs = {'name': 'fake-security-group-name'}
+ self.check_service_client_function(
+ self.client.create_security_group,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_SECURITY_GROUP,
+ bytes_body,
+ status=201,
+ mock_args=['v2.0/security-groups',
+ json.dumps({"security_group": kwargs})],
+ **kwargs)
+
+ def _test_show_security_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_security_group,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_SECURITY_GROUP,
+ bytes_body,
+ security_group_id=self.FAKE_SEC_GROUP_ID,
+ mock_args='v2.0/security-groups/%s' % self.FAKE_SEC_GROUP_ID)
+
+ def _test_update_security_group(self, bytes_body=False):
+ kwargs = {'name': 'updated-security-group-name'}
+ resp_body = copy.deepcopy(self.FAKE_SECURITY_GROUP)
+ resp_body["security_group"]["name"] = 'updated-security-group-name'
+
+ self.check_service_client_function(
+ self.client.update_security_group,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ resp_body,
+ bytes_body,
+ security_group_id=self.FAKE_SEC_GROUP_ID,
+ mock_args=['v2.0/security-groups/%s' % self.FAKE_SEC_GROUP_ID,
+ json.dumps({'security_group': kwargs})],
+ **kwargs)
+
+ def test_list_security_groups_with_str_body(self):
+ self._test_list_security_groups()
+
+ def test_list_security_groups_with_bytes_body(self):
+ self._test_list_security_groups(bytes_body=True)
+
+ def test_create_security_group_with_str_body(self):
+ self._test_create_security_group()
+
+ def test_create_security_group_with_bytes_body(self):
+ self._test_create_security_group(bytes_body=True)
+
+ def test_show_security_group_with_str_body(self):
+ self._test_show_security_group()
+
+ def test_show_security_group_with_bytes_body(self):
+ self._test_show_security_group(bytes_body=True)
+
+ def test_update_security_group_with_str_body(self):
+ self._test_update_security_group()
+
+ def test_update_security_group_with_bytes_body(self):
+ self._test_update_security_group(bytes_body=True)
+
+ def test_delete_security_group(self):
+ self.check_service_client_function(
+ self.client.delete_security_group,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ status=204,
+ security_group_id=self.FAKE_SEC_GROUP_ID,
+ mock_args='v2.0/security-groups/%s' % self.FAKE_SEC_GROUP_ID)
diff --git a/tempest/tests/lib/services/network/test_tags_client.py b/tempest/tests/lib/services/network/test_tags_client.py
new file mode 100644
index 0000000..dbe50a0
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_tags_client.py
@@ -0,0 +1,123 @@
+# Copyright 2017 AT&T Corporation.
+# 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.network import tags_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestTagsClient(base.BaseServiceTest):
+
+ FAKE_TAGS = {
+ "tags": [
+ "red",
+ "blue"
+ ]
+ }
+
+ FAKE_RESOURCE_TYPE = 'network'
+
+ FAKE_RESOURCE_ID = '7a8f904b-c1ed-4446-a87d-60440c02934b'
+
+ def setUp(self):
+ super(TestTagsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = tags_client.TagsClient(
+ fake_auth, 'network', 'regionOne')
+
+ def _test_update_all_tags(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_all_tags,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ self.FAKE_TAGS,
+ bytes_body,
+ resource_type=self.FAKE_RESOURCE_TYPE,
+ resource_id=self.FAKE_RESOURCE_ID,
+ tags=self.FAKE_TAGS)
+
+ def _test_check_tag_existence(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.check_tag_existence,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ {},
+ bytes_body,
+ resource_type=self.FAKE_RESOURCE_TYPE,
+ resource_id=self.FAKE_RESOURCE_ID,
+ tag=self.FAKE_TAGS['tags'][0],
+ status=204)
+
+ def _test_create_tag(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_tag,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ bytes_body,
+ resource_type=self.FAKE_RESOURCE_TYPE,
+ resource_id=self.FAKE_RESOURCE_ID,
+ tag=self.FAKE_TAGS['tags'][0],
+ status=201)
+
+ def _test_list_tags(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_tags,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_TAGS,
+ bytes_body,
+ resource_type=self.FAKE_RESOURCE_TYPE,
+ resource_id=self.FAKE_RESOURCE_ID)
+
+ def test_update_all_tags_with_str_body(self):
+ self._test_update_all_tags()
+
+ def test_update_all_tags_with_bytes_body(self):
+ self._test_update_all_tags(bytes_body=True)
+
+ def test_delete_all_tags(self):
+ self.check_service_client_function(
+ self.client.delete_all_tags,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ resource_type=self.FAKE_RESOURCE_TYPE,
+ resource_id=self.FAKE_RESOURCE_ID,
+ status=204)
+
+ def test_check_tag_existence_with_str_body(self):
+ self._test_check_tag_existence()
+
+ def test_check_tag_existence_with_bytes_body(self):
+ self._test_check_tag_existence(bytes_body=True)
+
+ def test_create_tag_with_str_body(self):
+ self._test_create_tag()
+
+ def test_create_tag_with_bytes_body(self):
+ self._test_create_tag(bytes_body=True)
+
+ def test_list_tags_with_str_body(self):
+ self._test_list_tags()
+
+ def test_list_tags_with_bytes_body(self):
+ self._test_list_tags(bytes_body=True)
+
+ def test_delete_tag(self):
+ self.check_service_client_function(
+ self.client.delete_tag,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ resource_type=self.FAKE_RESOURCE_TYPE,
+ resource_id=self.FAKE_RESOURCE_ID,
+ tag=self.FAKE_TAGS['tags'][0],
+ status=204)
diff --git a/tempest/tests/lib/services/volume/v2/test_capabilities_client.py b/tempest/tests/lib/services/volume/v2/test_capabilities_client.py
new file mode 100644
index 0000000..3d3f1e1
--- /dev/null
+++ b/tempest/tests/lib/services/volume/v2/test_capabilities_client.py
@@ -0,0 +1,77 @@
+# Copyright 2017 AT&T Corporation.
+# 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.volume.v2 import capabilities_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestCapabilitiesClient(base.BaseServiceTest):
+
+ FAKE_BACKEND_CAPABILITIES = {
+ "namespace": "OS::Storage::Capabilities::fake",
+ "vendor_name": "OpenStack",
+ "volume_backend_name": "lvmdriver-1",
+ "pool_name": "pool",
+ "driver_version": "2.0.0",
+ "storage_protocol": "iSCSI",
+ "display_name": "Capabilities of Cinder LVM driver",
+ "description": (
+ "These are volume type options provided by Cinder LVM driver."),
+ "visibility": "public",
+ "replication_targets": [],
+ "properties": {
+ "compression": {
+ "title": "Compression",
+ "description": "Enables compression.",
+ "type": "boolean"
+ },
+ "qos": {
+ "title": "QoS",
+ "description": "Enables QoS.",
+ "type": "boolean"
+ },
+ "replication": {
+ "title": "Replication",
+ "description": "Enables replication.",
+ "type": "boolean"
+ },
+ "thin_provisioning": {
+ "title": "Thin Provisioning",
+ "description": "Sets thin provisioning.",
+ "type": "boolean"
+ }
+ }
+ }
+
+ def setUp(self):
+ super(TestCapabilitiesClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = capabilities_client.CapabilitiesClient(
+ fake_auth, 'volume', 'regionOne')
+
+ def _test_show_backend_capabilities(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_backend_capabilities,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_BACKEND_CAPABILITIES,
+ bytes_body,
+ host='lvmdriver-1')
+
+ def test_show_backend_capabilities_with_str_body(self):
+ self._test_show_backend_capabilities()
+
+ def test_show_backend_capabilities_with_bytes_body(self):
+ self._test_show_backend_capabilities(bytes_body=True)