Merge "Remove wait_for_volume_status from compute client"
diff --git a/openstack-common.conf b/openstack-common.conf
index 1920295..16ba6a7 100644
--- a/openstack-common.conf
+++ b/openstack-common.conf
@@ -3,6 +3,8 @@
# The list of modules to copy from openstack-common
module=install_venv_common
module=versionutils
+module=with_venv
+module=install_venv
# The base module to hold the copy of openstack.common
base=tempest
diff --git a/requirements.txt b/requirements.txt
index d15a5a1..66e5b16 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -24,3 +24,4 @@
testscenarios>=0.4
tempest-lib>=0.6.1
PyYAML>=3.1.0
+stevedore>=1.5.0 # Apache-2.0
diff --git a/run_tempest.sh b/run_tempest.sh
index 5a9b742..0f32045 100755
--- a/run_tempest.sh
+++ b/run_tempest.sh
@@ -20,7 +20,7 @@
}
testrargs=""
-venv=.venv
+venv=${VENV:-.venv}
with_venv=tools/with_venv.sh
serial=0
always_venv=0
diff --git a/run_tests.sh b/run_tests.sh
index 971f89b..9a158e4 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -19,7 +19,7 @@
testrargs=""
just_pep8=0
-venv=.venv
+venv=${VENV:-.venv}
with_venv=tools/with_venv.sh
serial=0
always_venv=0
diff --git a/tempest/api/compute/admin/test_floating_ips_bulk.py b/tempest/api/compute/admin/test_floating_ips_bulk.py
index 5c45dd8..4ac1915 100644
--- a/tempest/api/compute/admin/test_floating_ips_bulk.py
+++ b/tempest/api/compute/admin/test_floating_ips_bulk.py
@@ -34,7 +34,7 @@
@classmethod
def setup_clients(cls):
super(FloatingIPsBulkAdminTestJSON, cls).setup_clients()
- cls.client = cls.os_adm.floating_ips_client
+ cls.client = cls.os_adm.floating_ips_bulk_client
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 0062c1e..51a03f5 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -52,7 +52,7 @@
@test.idempotent_id('51717b38-bdc1-458b-b636-1cf82d99f62f')
def test_list_servers_by_admin(self):
# Listing servers by admin user returns empty list by default
- body = self.client.list_servers_with_detail()
+ body = self.client.list_servers(detail=True)
servers = body['servers']
self.assertEqual([], servers)
@@ -61,7 +61,7 @@
# Filter the list of servers by server error status
params = {'status': 'error'}
self.client.reset_state(self.s1_id, state='error')
- body = self.non_admin_client.list_servers(params)
+ body = self.non_admin_client.list_servers(**params)
# Reset server's state to 'active'
self.client.reset_state(self.s1_id, state='active')
# Verify server's state
@@ -77,7 +77,7 @@
# Listing servers by admin user with all tenants parameter
# Here should be listed all servers
params = {'all_tenants': ''}
- body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers(detail=True, **params)
servers = body['servers']
servers_name = map(lambda x: x['name'], servers)
@@ -91,14 +91,14 @@
# List the primary tenant but get nothing due to odd specified behavior
tenant_id = self.non_admin_client.tenant_id
params = {'tenant_id': tenant_id}
- body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers(detail=True, **params)
servers = body['servers']
self.assertEqual([], servers)
# List the admin tenant which has no servers
admin_tenant_id = self.client.tenant_id
params = {'all_tenants': '', 'tenant_id': admin_tenant_id}
- body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers(detail=True, **params)
servers = body['servers']
self.assertEqual([], servers)
@@ -118,10 +118,10 @@
self.assertEqual(server['status'], 'ACTIVE')
hostname = server[self._host_key]
params = {'host': hostname}
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
nonexistent_params = {'host': 'nonexistent_host'}
- nonexistent_body = self.client.list_servers(nonexistent_params)
+ nonexistent_body = self.client.list_servers(**nonexistent_params)
nonexistent_servers = nonexistent_body['servers']
self.assertIn(test_server['id'], map(lambda x: x['id'], servers))
self.assertNotIn(test_server['id'],
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 2b36180..ea8e112 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -57,9 +57,11 @@
def setup_clients(cls):
super(BaseComputeTest, cls).setup_clients()
cls.servers_client = cls.os.servers_client
+ cls.server_groups_client = cls.os.server_groups_client
cls.flavors_client = cls.os.flavors_client
cls.images_client = cls.os.images_client
cls.extensions_client = cls.os.extensions_client
+ cls.floating_ip_pools_client = cls.os.floating_ip_pools_client
cls.floating_ips_client = cls.os.floating_ips_client
cls.keypairs_client = cls.os.keypairs_client
cls.security_groups_client = cls.os.security_groups_client
@@ -183,7 +185,7 @@
LOG.debug('Clearing server groups: %s', ','.join(cls.server_groups))
for server_group_id in cls.server_groups:
try:
- cls.servers_client.delete_server_group(server_group_id)
+ cls.server_groups_client.delete_server_group(server_group_id)
except lib_exc.NotFound:
# The server-group may have already been deleted which is OK.
pass
@@ -231,7 +233,7 @@
name = data_utils.rand_name(cls.__name__ + "-Server-Group")
if policy is None:
policy = ['affinity']
- body = cls.servers_client.create_server_group(name, policy)
+ body = cls.server_groups_client.create_server_group(name, policy)
cls.server_groups.append(body['id'])
return body
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips.py b/tempest/api/compute/floating_ips/test_list_floating_ips.py
index ad52b8c..d26a5e5 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -23,6 +23,7 @@
def setup_clients(cls):
super(FloatingIPDetailsTestJSON, cls).setup_clients()
cls.client = cls.floating_ips_client
+ cls.pools_client = cls.floating_ip_pools_client
@classmethod
def resource_setup(cls):
@@ -76,6 +77,6 @@
@test.services('network')
def test_list_floating_ip_pools(self):
# Positive test:Should return the list of floating IP Pools
- floating_ip_pools = self.client.list_floating_ip_pools()
+ floating_ip_pools = self.pools_client.list_floating_ip_pools()
self.assertNotEqual(0, len(floating_ip_pools),
"Expected floating IP Pools. Got zero.")
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 8b0e1a4..94b6cf0 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -91,7 +91,7 @@
@test.idempotent_id('585e934c-448e-43c4-acbf-d06a9b899997')
def test_list_servers_with_detail(self):
# The created server should be in the detailed list of all servers
- body = self.client.list_servers_with_detail()
+ body = self.client.list_servers(detail=True)
servers = body['servers']
found = any([i for i in servers if i['id'] == self.server['id']])
self.assertTrue(found)
@@ -121,17 +121,18 @@
# Create a server with the scheduler hint "group".
name = data_utils.rand_name('server_group')
policies = ['affinity']
- body = self.client.create_server_group(name=name,
- policies=policies)
+ body = self.server_groups_client.create_server_group(
+ name=name, policies=policies)
group_id = body['id']
- self.addCleanup(self.client.delete_server_group, group_id)
+ self.addCleanup(self.server_groups_client.delete_server_group,
+ group_id)
hints = {'group': group_id}
server = self.create_test_server(sched_hints=hints,
wait_until='ACTIVE')
# Check a server is in the group
- server_group = self.client.get_server_group(group_id)
+ server_group = self.server_groups_client.get_server_group(group_id)
self.assertIn(server['id'], server_group['members'])
@test.idempotent_id('0578d144-ed74-43f8-8e57-ab10dbf9b3c2')
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 326334c..6d546d8 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -92,7 +92,7 @@
def test_list_servers_filter_by_image(self):
# Filter the list of servers by image
params = {'image': self.image_ref}
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
@@ -103,7 +103,7 @@
def test_list_servers_filter_by_flavor(self):
# Filter the list of servers by flavor
params = {'flavor': self.flavor_ref_alt}
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
self.assertNotIn(self.s1['id'], map(lambda x: x['id'], servers))
@@ -114,7 +114,7 @@
def test_list_servers_filter_by_server_name(self):
# Filter the list of servers by server name
params = {'name': self.s1_name}
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -125,7 +125,7 @@
def test_list_servers_filter_by_server_status(self):
# Filter the list of servers by server status
params = {'status': 'active'}
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
@@ -139,7 +139,7 @@
self.client.stop(self.s1['id'])
self.client.wait_for_server_status(self.s1['id'],
'SHUTOFF')
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
self.client.start(self.s1['id'])
self.client.wait_for_server_status(self.s1['id'],
'ACTIVE')
@@ -153,21 +153,21 @@
def test_list_servers_filter_by_limit(self):
# Verify only the expected number of servers are returned
params = {'limit': 1}
- servers = self.client.list_servers(params)
+ servers = self.client.list_servers(**params)
self.assertEqual(1, len([x for x in servers['servers'] if 'id' in x]))
@test.idempotent_id('b1495414-2d93-414c-8019-849afe8d319e')
def test_list_servers_filter_by_zero_limit(self):
# Verify only the expected number of servers are returned
params = {'limit': 0}
- servers = self.client.list_servers(params)
+ servers = self.client.list_servers(**params)
self.assertEqual(0, len(servers['servers']))
@test.idempotent_id('37791bbd-90c0-4de0-831e-5f38cba9c6b3')
def test_list_servers_filter_by_exceed_limit(self):
# Verify only the expected number of servers are returned
params = {'limit': 100000}
- servers = self.client.list_servers(params)
+ servers = self.client.list_servers(**params)
all_servers = self.client.list_servers()
self.assertEqual(len([x for x in all_servers['servers'] if 'id' in x]),
len([x for x in servers['servers'] if 'id' in x]))
@@ -177,7 +177,7 @@
def test_list_servers_detailed_filter_by_image(self):
# Filter the detailed list of servers by image
params = {'image': self.image_ref}
- body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers(detail=True, **params)
servers = body['servers']
self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
@@ -188,7 +188,7 @@
def test_list_servers_detailed_filter_by_flavor(self):
# Filter the detailed list of servers by flavor
params = {'flavor': self.flavor_ref_alt}
- body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers(detail=True, **params)
servers = body['servers']
self.assertNotIn(self.s1['id'], map(lambda x: x['id'], servers))
@@ -199,7 +199,7 @@
def test_list_servers_detailed_filter_by_server_name(self):
# Filter the detailed list of servers by server name
params = {'name': self.s1_name}
- body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers(detail=True, **params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -210,7 +210,7 @@
def test_list_servers_detailed_filter_by_server_status(self):
# Filter the detailed list of servers by server status
params = {'status': 'active'}
- body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers(detail=True, **params)
servers = body['servers']
test_ids = [s['id'] for s in (self.s1, self.s2, self.s3)]
@@ -224,7 +224,7 @@
def test_list_servers_filtered_by_name_wildcard(self):
# List all servers that contains '-instance' in name
params = {'name': '-instance'}
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -235,7 +235,7 @@
part_name = self.s1_name[6:-1]
params = {'name': part_name}
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -248,7 +248,7 @@
regexes = ['^.*\-instance\-[0-9]+$', '^.*\-instance\-.*$']
for regex in regexes:
params = {'name': regex}
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -259,7 +259,7 @@
part_name = self.s1_name[-10:]
params = {'name': part_name}
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -282,7 +282,7 @@
else:
msg = "Skipped until bug 1450859 is resolved"
raise self.skipException(msg)
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -304,7 +304,7 @@
params = {'ip': ip}
else:
params = {'ip6': ip}
- body = self.client.list_servers(params)
+ body = self.client.list_servers(**params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -315,5 +315,5 @@
def test_list_servers_detailed_limit_results(self):
# Verify only the expected number of detailed results are returned
params = {'limit': 1}
- servers = self.client.list_servers_with_detail(params)
+ servers = self.client.list_servers(detail=True, **params)
self.assertEqual(1, len(servers['servers']))
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index fd4d902..def6cf5 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -68,7 +68,7 @@
def test_list_servers_by_non_existing_image(self):
# Listing servers for a non existing image returns empty list
non_existing_image = '1234abcd-zzz0-aaa9-ppp3-0987654abcde'
- body = self.client.list_servers(dict(image=non_existing_image))
+ body = self.client.list_servers(image=non_existing_image)
servers = body['servers']
self.assertEqual([], servers)
@@ -77,7 +77,7 @@
def test_list_servers_by_non_existing_flavor(self):
# Listing servers by non existing flavor returns empty list
non_existing_flavor = 1234
- body = self.client.list_servers(dict(flavor=non_existing_flavor))
+ body = self.client.list_servers(flavor=non_existing_flavor)
servers = body['servers']
self.assertEqual([], servers)
@@ -86,7 +86,7 @@
def test_list_servers_by_non_existing_server_name(self):
# Listing servers for a non existent server name returns empty list
non_existing_name = 'junk_server_1234'
- body = self.client.list_servers(dict(name=non_existing_name))
+ body = self.client.list_servers(name=non_existing_name)
servers = body['servers']
self.assertEqual([], servers)
@@ -95,21 +95,21 @@
def test_list_servers_status_non_existing(self):
# Return an empty list when invalid status is specified
non_existing_status = 'BALONEY'
- body = self.client.list_servers(dict(status=non_existing_status))
+ body = self.client.list_servers(status=non_existing_status)
servers = body['servers']
self.assertEqual([], servers)
@test.idempotent_id('12c80a9f-2dec-480e-882b-98ba15757659')
def test_list_servers_by_limits(self):
# List servers by specifying limits
- body = self.client.list_servers({'limit': 1})
+ body = self.client.list_servers(limit=1)
self.assertEqual(1, len([x for x in body['servers'] if 'id' in x]))
@test.attr(type=['negative'])
@test.idempotent_id('d47c17fb-eebd-4287-8e95-f20a7e627b18')
def test_list_servers_by_limits_greater_than_actual_count(self):
# List servers by specifying a greater value for limit
- body = self.client.list_servers({'limit': 100})
+ body = self.client.list_servers(limit=100)
self.assertEqual(len(self.existing_fixtures), len(body['servers']))
@test.attr(type=['negative'])
@@ -117,28 +117,29 @@
def test_list_servers_by_limits_pass_string(self):
# Return an error if a string value is passed for limit
self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
- {'limit': 'testing'})
+ limit='testing')
@test.attr(type=['negative'])
@test.idempotent_id('62610dd9-4713-4ee0-8beb-fd2c1aa7f950')
def test_list_servers_by_limits_pass_negative_value(self):
# Return an error if a negative value for limit is passed
self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
- {'limit': -1})
+ limit=-1)
@test.attr(type=['negative'])
@test.idempotent_id('87d12517-e20a-4c9c-97b6-dd1628d6d6c9')
def test_list_servers_by_changes_since_invalid_date(self):
# Return an error when invalid date format is passed
+ params = {'changes-since': '2011/01/01'}
self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
- {'changes-since': '2011/01/01'})
+ **params)
@test.attr(type=['negative'])
@test.idempotent_id('74745ad8-b346-45b5-b9b8-509d7447fc1f')
def test_list_servers_by_changes_since_future_date(self):
# Return an empty list when a date in the future is passed
changes_since = {'changes-since': '2051-01-01T12:34:00Z'}
- body = self.client.list_servers(changes_since)
+ body = self.client.list_servers(**changes_since)
self.assertEqual(0, len(body['servers']))
@test.attr(type=['negative'])
@@ -146,7 +147,7 @@
def test_list_servers_detail_server_is_deleted(self):
# Server details are not listed for a deleted server
deleted_ids = [s['id'] for s in self.deleted_fixtures]
- body = self.client.list_servers_with_detail()
+ body = self.client.list_servers(detail=True)
servers = body['servers']
actual = [srv for srv in servers
if srv['id'] in deleted_ids]
diff --git a/tempest/api/compute/servers/test_server_group.py b/tempest/api/compute/servers/test_server_group.py
index f6dd5e3..0e7c1eb 100644
--- a/tempest/api/compute/servers/test_server_group.py
+++ b/tempest/api/compute/servers/test_server_group.py
@@ -37,7 +37,7 @@
@classmethod
def setup_clients(cls):
super(ServerGroupTestJSON, cls).setup_clients()
- cls.client = cls.servers_client
+ cls.client = cls.server_groups_client
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/identity/v2/test_tokens.py b/tempest/api/identity/v2/test_tokens.py
index 5a8afa0..3b508f4 100644
--- a/tempest/api/identity/v2/test_tokens.py
+++ b/tempest/api/identity/v2/test_tokens.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo_utils import timeutils
+import six
from tempest.api.identity import base
from tempest import test
@@ -30,9 +32,19 @@
password = creds.password
tenant_name = creds.tenant_name
- body = token_client.auth(username,
- password,
- tenant_name)
+ body = token_client.auth(username, password, tenant_name)
+ self.assertNotEmpty(body['token']['id'])
+ self.assertIsInstance(body['token']['id'], six.string_types)
+
+ now = timeutils.utcnow()
+ expires_at = timeutils.normalize_time(
+ timeutils.parse_isotime(body['token']['expires']))
+ self.assertGreater(expires_at, now)
+
+ self.assertEqual(body['token']['tenant']['id'],
+ creds.credentials.tenant_id)
self.assertEqual(body['token']['tenant']['name'],
tenant_name)
+
+ self.assertEqual(body['user']['id'], creds.credentials.user_id)
diff --git a/tempest/api/identity/v3/test_tokens.py b/tempest/api/identity/v3/test_tokens.py
index ab4a09f..3151763 100644
--- a/tempest/api/identity/v3/test_tokens.py
+++ b/tempest/api/identity/v3/test_tokens.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo_utils import timeutils
+import six
from tempest.api.identity import base
from tempest import test
@@ -26,8 +28,25 @@
user_id = creds.user_id
username = creds.username
password = creds.password
- resp = self.non_admin_token.auth(user_id=user_id,
- password=password)
- subject_name = resp['token']['user']['name']
+ token_id, resp = self.non_admin_token.get_token(user_id=user_id,
+ password=password,
+ auth_data=True)
+
+ self.assertNotEmpty(token_id)
+ self.assertIsInstance(token_id, six.string_types)
+
+ now = timeutils.utcnow()
+ expires_at = timeutils.normalize_time(
+ timeutils.parse_isotime(resp['expires_at']))
+ self.assertGreater(resp['expires_at'],
+ resp['issued_at'])
+ self.assertGreater(expires_at, now)
+
+ subject_id = resp['user']['id']
+ self.assertEqual(subject_id, user_id)
+
+ subject_name = resp['user']['name']
self.assertEqual(subject_name, username)
+
+ self.assertEqual(resp['methods'][0], 'password')
diff --git a/tempest/api/image/v2/test_images_member.py b/tempest/api/image/v2/test_images_member.py
index d497005..d89803d 100644
--- a/tempest/api/image/v2/test_images_member.py
+++ b/tempest/api/image/v2/test_images_member.py
@@ -89,3 +89,19 @@
def test_get_image_members_schema(self):
body = self.os_img_client.show_schema("members")
self.assertEqual("members", body['name'])
+
+ @test.idempotent_id('cb961424-3f68-4d21-8e36-30ad66fb6bfb')
+ def test_get_private_image(self):
+ image_id = self._create_image()
+ member = self.os_img_client.add_image_member(image_id,
+ self.alt_tenant_id)
+ self.assertEqual(member['member_id'], self.alt_tenant_id)
+ self.assertEqual(member['image_id'], image_id)
+ self.assertEqual(member['status'], 'pending')
+ self.assertNotIn(image_id, self._list_image_ids_as_alt())
+ self.alt_img_client.update_image_member(image_id,
+ self.alt_tenant_id,
+ {'status': 'accepted'})
+ self.assertIn(image_id, self._list_image_ids_as_alt())
+ self.os_img_client.remove_image_member(image_id, self.alt_tenant_id)
+ self.assertNotIn(image_id, self._list_image_ids_as_alt())
diff --git a/tempest/api/network/test_networks_negative.py b/tempest/api/network/test_networks_negative.py
index 520342e..5dc1c21 100644
--- a/tempest/api/network/test_networks_negative.py
+++ b/tempest/api/network/test_networks_negative.py
@@ -57,3 +57,38 @@
non_exist_id = data_utils.rand_name('network')
self.assertRaises(lib_exc.NotFound, self.client.delete_network,
non_exist_id)
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('1cc47884-ac52-4415-a31c-e7ce5474a868')
+ def test_update_non_existent_subnet(self):
+ non_exist_id = data_utils.rand_uuid()
+ self.assertRaises(lib_exc.NotFound, self.client.update_subnet,
+ non_exist_id, name='new_name')
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('a176c859-99fb-42ec-a208-8a85b552a239')
+ def test_delete_non_existent_subnet(self):
+ non_exist_id = data_utils.rand_uuid()
+ self.assertRaises(lib_exc.NotFound,
+ self.client.delete_subnet, non_exist_id)
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('13d3b106-47e6-4b9b-8d53-dae947f092fe')
+ def test_create_port_on_non_existent_network(self):
+ non_exist_net_id = data_utils.rand_uuid()
+ self.assertRaises(lib_exc.NotFound,
+ self.client.create_port, network_id=non_exist_net_id)
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('cf8eef21-4351-4f53-adcd-cc5cb1e76b92')
+ def test_update_non_existent_port(self):
+ non_exist_port_id = data_utils.rand_uuid()
+ self.assertRaises(lib_exc.NotFound, self.client.update_port,
+ non_exist_port_id, name='new_name')
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('49ec2bbd-ac2e-46fd-8054-798e679ff894')
+ def test_delete_non_existent_port(self):
+ non_exist_port_id = data_utils.rand_uuid()
+ self.assertRaises(lib_exc.NotFound,
+ self.client.delete_port, non_exist_port_id)
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index 4c774da..d1eb694 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -14,6 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from six.moves.urllib import parse
+
from tempest.api.volume import base
from tempest import test
@@ -87,3 +89,101 @@
_list_details_with_multiple_params()
_list_details_with_multiple_params(sort_dir='desc')
+
+ def _test_pagination(self, resource, ids=None, limit=1, **kwargs):
+ """Check list pagination functionality for a resource.
+
+ This method requests the list of resources and follows pagination
+ links.
+
+ If an iterable is supplied in ids it will check that all ids are
+ retrieved and that only those are listed, that we will get a next
+ link for an empty page if the number of items is divisible by used
+ limit (this is expected behavior).
+
+ We can specify number of items per request using limit argument.
+ """
+
+ # Get list method for the type of resource from the client
+ client = getattr(self, resource + '_client')
+ method = getattr(client, 'list_' + resource)
+
+ # Include limit in params for list request
+ params = kwargs.pop('params', {})
+ params['limit'] = limit
+
+ # Store remaining items we are expecting from list
+ if ids is not None:
+ remaining = list(ids)
+ else:
+ remaining = None
+
+ # Mark that we are not comming from a next link
+ next = None
+
+ while True:
+ # Get a list page
+ response = method(return_body=True, params=params, **kwargs)
+
+ # If we have to check ids
+ if remaining is not None:
+ # Confirm we receive expected number of elements
+ num_expected = min(len(remaining), limit)
+ self.assertEqual(num_expected, len(response[resource]),
+ 'Requested %(#expect)d but got %(#received)d '
+ % {'#expect': num_expected,
+ '#received': len(response[resource])})
+
+ # For each received element
+ for element in response[resource]:
+ element_id = element['id']
+ # Check it's one of expected ids
+ self.assertIn(element_id,
+ ids,
+ 'Id %(id)s is not in expected ids %(ids)s' %
+ {'id': element_id, 'ids': ids})
+ # If not in remaining, we have received it twice
+ self.assertIn(element_id,
+ remaining,
+ 'Id %s was received twice' % element_id)
+ # We no longer expect it
+ remaining.remove(element_id)
+
+ # If we come from a next link check that absolute url is the same
+ # as the one used for this request
+ if next:
+ self.assertEqual(next, response.response['content-location'])
+
+ # Get next from response
+ next = None
+ for link in response.get(resource + '_links', ()):
+ if link['rel'] == 'next':
+ next = link['href']
+ break
+
+ # Check if we have next and we shouldn't or the other way around
+ if remaining is not None:
+ if remaining or (num_expected and len(ids) % limit == 0):
+ self.assertIsNotNone(next, 'Missing link to next page')
+ else:
+ self.assertIsNone(next, 'Unexpected link to next page')
+
+ # If we can follow to the next page, get params from url to make
+ # request in the form of a relative URL
+ if next:
+ params = parse.urlparse(next).query
+
+ # If cannot follow make sure it's because we have finished
+ else:
+ self.assertListEqual([], remaining or [],
+ 'No more pages reported, but still '
+ 'missing ids %s' % remaining)
+ break
+
+ @test.idempotent_id('e9138a2c-f67b-4796-8efa-635c196d01de')
+ def test_volume_list_details_pagination(self):
+ self._test_pagination('volumes', ids=self.volume_id_list, detail=True)
+
+ @test.idempotent_id('af55e775-8e4b-4feb-8719-215c43b0238c')
+ def test_volume_list_pagination(self):
+ self._test_pagination('volumes', ids=self.volume_id_list, detail=False)
diff --git a/tempest/api_schema/response/compute/v2_1/fixed_ips.py b/tempest/api_schema/response/compute/v2_1/fixed_ips.py
index 6d5ba67..3586b70 100644
--- a/tempest/api_schema/response/compute/v2_1/fixed_ips.py
+++ b/tempest/api_schema/response/compute/v2_1/fixed_ips.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.api_schema.response.compute.v2_1 import parameter_types
+
get_fixed_ip = {
'status_code': [200],
'response_body': {
@@ -20,10 +22,7 @@
'fixed_ip': {
'type': 'object',
'properties': {
- 'address': {
- 'type': 'string',
- 'format': 'ip-address'
- },
+ 'address': parameter_types.ip_address,
'cidr': {'type': 'string'},
'host': {'type': 'string'},
'hostname': {'type': 'string'}
diff --git a/tempest/api_schema/response/compute/v2_1/floating_ips.py b/tempest/api_schema/response/compute/v2_1/floating_ips.py
index 28dd40a..3551681 100644
--- a/tempest/api_schema/response/compute/v2_1/floating_ips.py
+++ b/tempest/api_schema/response/compute/v2_1/floating_ips.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.api_schema.response.compute.v2_1 import parameter_types
+
common_floating_ip_info = {
'type': 'object',
'properties': {
@@ -21,14 +23,8 @@
'id': {'type': ['integer', 'string']},
'pool': {'type': ['string', 'null']},
'instance_id': {'type': ['string', 'null']},
- 'ip': {
- 'type': 'string',
- 'format': 'ip-address'
- },
- 'fixed_ip': {
- 'type': ['string', 'null'],
- 'format': 'ip-address'
- }
+ 'ip': parameter_types.ip_address,
+ 'fixed_ip': parameter_types.ip_address
},
'additionalProperties': False,
'required': ['id', 'pool', 'instance_id',
@@ -131,18 +127,12 @@
'items': {
'type': 'object',
'properties': {
- 'address': {
- 'type': 'string',
- 'format': 'ip-address'
- },
+ 'address': parameter_types.ip_address,
'instance_uuid': {'type': ['string', 'null']},
'interface': {'type': ['string', 'null']},
'pool': {'type': ['string', 'null']},
'project_id': {'type': ['string', 'null']},
- 'fixed_ip': {
- 'type': ['string', 'null'],
- 'format': 'ip-address'
- }
+ 'fixed_ip': parameter_types.ip_address
},
'additionalProperties': False,
# NOTE: fixed_ip is introduced after JUNO release,
diff --git a/tempest/api_schema/response/compute/v2_1/hypervisors.py b/tempest/api_schema/response/compute/v2_1/hypervisors.py
index e24389d..05901b6 100644
--- a/tempest/api_schema/response/compute/v2_1/hypervisors.py
+++ b/tempest/api_schema/response/compute/v2_1/hypervisors.py
@@ -14,6 +14,8 @@
import copy
+from tempest.api_schema.response.compute.v2_1 import parameter_types
+
get_hypervisor_statistics = {
'status_code': [200],
'response_body': {
@@ -57,10 +59,7 @@
'cpu_info': {'type': 'string'},
'current_workload': {'type': 'integer'},
'disk_available_least': {'type': ['integer', 'null']},
- 'host_ip': {
- 'type': 'string',
- 'format': 'ip-address'
- },
+ 'host_ip': parameter_types.ip_address,
'free_disk_gb': {'type': 'integer'},
'free_ram_mb': {'type': 'integer'},
'hypervisor_hostname': {'type': 'string'},
diff --git a/tempest/api_schema/response/compute/v2_1/interfaces.py b/tempest/api_schema/response/compute/v2_1/interfaces.py
index b18fba6..130775b 100644
--- a/tempest/api_schema/response/compute/v2_1/interfaces.py
+++ b/tempest/api_schema/response/compute/v2_1/interfaces.py
@@ -27,10 +27,7 @@
'type': 'string',
'format': 'uuid'
},
- 'ip_address': {
- 'type': 'string',
- 'format': 'ipv4'
- }
+ 'ip_address': parameter_types.ip_address
},
'additionalProperties': False,
'required': ['subnet_id', 'ip_address']
diff --git a/tempest/api_schema/response/compute/v2_1/parameter_types.py b/tempest/api_schema/response/compute/v2_1/parameter_types.py
index 7b4264c..07cc890 100644
--- a/tempest/api_schema/response/compute/v2_1/parameter_types.py
+++ b/tempest/api_schema/response/compute/v2_1/parameter_types.py
@@ -33,14 +33,27 @@
'pattern': '(?:[a-f0-9]{2}:){5}[a-f0-9]{2}'
}
+ip_address = {
+ 'oneOf': [
+ {
+ 'type': 'string',
+ 'oneOf': [
+ {'format': 'ipv4'},
+ {'format': 'ipv6'}
+ ]
+ },
+ {'type': 'null'}
+ ]
+}
+
access_ip_v4 = {
'type': 'string',
- 'anyOf': [{'format': 'ipv4'}, {'enum': ['']}]
+ 'oneOf': [{'format': 'ipv4'}, {'enum': ['']}]
}
access_ip_v6 = {
'type': 'string',
- 'anyOf': [{'format': 'ipv6'}, {'enum': ['']}]
+ 'oneOf': [{'format': 'ipv6'}, {'enum': ['']}]
}
addresses = {
@@ -55,7 +68,7 @@
'version': {'type': 'integer'},
'addr': {
'type': 'string',
- 'anyOf': [
+ 'oneOf': [
{'format': 'ipv4'},
{'format': 'ipv6'}
]
diff --git a/tempest/clients.py b/tempest/clients.py
index ab6bd43..6a2c601 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -41,6 +41,10 @@
ExtensionsClient
from tempest.services.compute.json.fixed_ips_client import FixedIPsClient
from tempest.services.compute.json.flavors_client import FlavorsClient
+from tempest.services.compute.json.floating_ip_pools_client import \
+ FloatingIpPoolsClient
+from tempest.services.compute.json.floating_ips_bulk_client import \
+ FloatingIpsBulkClient
from tempest.services.compute.json.floating_ips_client import \
FloatingIPsClient
from tempest.services.compute.json.hosts_client import HostsClient
@@ -63,6 +67,8 @@
SecurityGroupDefaultRulesClient
from tempest.services.compute.json.security_groups_client import \
SecurityGroupsClient
+from tempest.services.compute.json.server_groups_client import \
+ ServerGroupsClient
from tempest.services.compute.json.servers_client import ServersClient
from tempest.services.compute.json.services_client import ServicesClient
from tempest.services.compute.json.tenant_networks_client import \
@@ -263,6 +269,8 @@
enable_instance_password=CONF.compute_feature_enabled
.enable_instance_password,
**params)
+ self.server_groups_client = ServerGroupsClient(
+ self.auth_provider, **params)
self.limits_client = LimitsClient(self.auth_provider, **params)
self.images_client = ImagesClient(self.auth_provider, **params)
self.keypairs_client = KeyPairsClient(self.auth_provider, **params)
@@ -272,6 +280,10 @@
self.flavors_client = FlavorsClient(self.auth_provider, **params)
self.extensions_client = ExtensionsClient(self.auth_provider,
**params)
+ self.floating_ip_pools_client = FloatingIpPoolsClient(
+ self.auth_provider, **params)
+ self.floating_ips_bulk_client = FloatingIpsBulkClient(
+ self.auth_provider, **params)
self.floating_ips_client = FloatingIPsClient(self.auth_provider,
**params)
self.security_groups_client = SecurityGroupsClient(
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 8f0b4dc..95a8356 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -559,27 +559,27 @@
def _list_networks(self, *args, **kwargs):
"""List networks using admin creds """
- return self._admin_lister('networks')(*args, **kwargs)
+ networks_list = self.admin_manager.network_client.list_networks(
+ *args, **kwargs)
+ return networks_list['networks']
def _list_subnets(self, *args, **kwargs):
"""List subnets using admin creds """
- return self._admin_lister('subnets')(*args, **kwargs)
+ subnets_list = self.admin_manager.network_client.list_subnets(
+ *args, **kwargs)
+ return subnets_list['subnets']
def _list_routers(self, *args, **kwargs):
"""List routers using admin creds """
- return self._admin_lister('routers')(*args, **kwargs)
+ routers_list = self.admin_manager.network_client.list_routers(
+ *args, **kwargs)
+ return routers_list['routers']
def _list_ports(self, *args, **kwargs):
"""List ports using admin creds """
- return self._admin_lister('ports')(*args, **kwargs)
-
- def _admin_lister(self, resource_type):
- def temp(*args, **kwargs):
- temp_method = self.admin_manager.network_client.__getattr__(
- 'list_%s' % resource_type)
- resource_list = temp_method(*args, **kwargs)
- return resource_list[resource_type]
- return temp
+ ports_list = self.admin_manager.network_client.list_ports(
+ *args, **kwargs)
+ return ports_list['ports']
def _create_subnet(self, network, client=None, namestart='subnet-smoke',
**kwargs):
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index ffb35fb..1a18be5 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -102,7 +102,7 @@
**create_kwargs)
# needed because of bug 1199788
params = {'name': name}
- server_list = self.servers_client.list_servers(params)
+ server_list = self.servers_client.list_servers(**params)
self.servers = server_list['servers']
for server in self.servers:
# after deleting all servers - wait for all servers to clear
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 6461886..ff58eea 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -243,7 +243,7 @@
self.assertEqual(1, len(port_list))
old_port = port_list[0]
interface = self.interface_client.create_interface(
- server=server['id'],
+ server_id=server['id'],
network_id=self.new_net.id)
self.addCleanup(self.network_client.wait_for_resource_deletion,
'port',
diff --git a/tempest/scenario/test_swift_telemetry_middleware.py b/tempest/scenario/test_swift_telemetry_middleware.py
index 302ccbe..29ce1a0 100644
--- a/tempest/scenario/test_swift_telemetry_middleware.py
+++ b/tempest/scenario/test_swift_telemetry_middleware.py
@@ -74,7 +74,7 @@
called again.
"""
results = self.telemetry_client.list_samples(
- 'storage.api.request')
+ 'storage.objects.incoming.bytes')
LOG.debug('got samples %s', results)
# Extract container info from samples.
diff --git a/tempest/services/compute/json/certificates_client.py b/tempest/services/compute/json/certificates_client.py
index 15b019f..da1aa94 100644
--- a/tempest/services/compute/json/certificates_client.py
+++ b/tempest/services/compute/json/certificates_client.py
@@ -21,8 +21,8 @@
class CertificatesClient(service_client.ServiceClient):
- def show_certificate(self, id):
- url = "os-certificates/%s" % (id)
+ def show_certificate(self, certificate_id):
+ url = "os-certificates/%s" % certificate_id
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.get_certificate, resp, body)
diff --git a/tempest/services/compute/json/fixed_ips_client.py b/tempest/services/compute/json/fixed_ips_client.py
index 53a5476..b921107 100644
--- a/tempest/services/compute/json/fixed_ips_client.py
+++ b/tempest/services/compute/json/fixed_ips_client.py
@@ -22,15 +22,15 @@
class FixedIPsClient(service_client.ServiceClient):
def show_fixed_ip(self, fixed_ip):
- url = "os-fixed-ips/%s" % (fixed_ip)
+ url = "os-fixed-ips/%s" % fixed_ip
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.get_fixed_ip, resp, body)
return service_client.ResponseBody(resp, body['fixed_ip'])
- def reserve_fixed_ip(self, ip, body):
+ def reserve_fixed_ip(self, fixed_ip, body):
"""This reserves and unreserves fixed ips."""
- url = "os-fixed-ips/%s/action" % (ip)
+ url = "os-fixed-ips/%s/action" % fixed_ip
resp, body = self.post(url, json.dumps(body))
self.validate_response(schema.reserve_fixed_ip, resp, body)
return service_client.ResponseBody(resp)
diff --git a/tempest/services/compute/json/floating_ip_pools_client.py b/tempest/services/compute/json/floating_ip_pools_client.py
new file mode 100644
index 0000000..1cc411b
--- /dev/null
+++ b/tempest/services/compute/json/floating_ip_pools_client.py
@@ -0,0 +1,35 @@
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import json
+
+from six.moves.urllib import parse as urllib
+
+from tempest.api_schema.response.compute.v2_1 import floating_ips as schema
+from tempest.common import service_client
+
+
+class FloatingIpPoolsClient(service_client.ServiceClient):
+
+ def list_floating_ip_pools(self, params=None):
+ """Returns a list of all floating IP Pools."""
+ url = 'os-floating-ip-pools'
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+
+ resp, body = self.get(url)
+ body = json.loads(body)
+ self.validate_response(schema.list_floating_ip_pools, resp, body)
+ return service_client.ResponseBodyList(resp, body['floating_ip_pools'])
diff --git a/tempest/services/compute/json/floating_ips_bulk_client.py b/tempest/services/compute/json/floating_ips_bulk_client.py
new file mode 100644
index 0000000..c8e7350
--- /dev/null
+++ b/tempest/services/compute/json/floating_ips_bulk_client.py
@@ -0,0 +1,52 @@
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import json
+
+from tempest.api_schema.response.compute.v2_1 import floating_ips as schema
+from tempest.common import service_client
+
+
+class FloatingIpsBulkClient(service_client.ServiceClient):
+
+ def create_floating_ips_bulk(self, ip_range, pool, interface):
+ """Allocate floating IPs in bulk."""
+ post_body = {
+ 'ip_range': ip_range,
+ 'pool': pool,
+ 'interface': interface
+ }
+ post_body = json.dumps({'floating_ips_bulk_create': post_body})
+ resp, body = self.post('os-floating-ips-bulk', post_body)
+ body = json.loads(body)
+ self.validate_response(schema.create_floating_ips_bulk, resp, body)
+ return service_client.ResponseBody(resp,
+ body['floating_ips_bulk_create'])
+
+ def list_floating_ips_bulk(self):
+ """Returns a list of all floating IPs bulk."""
+ resp, body = self.get('os-floating-ips-bulk')
+ body = json.loads(body)
+ self.validate_response(schema.list_floating_ips_bulk, resp, body)
+ return service_client.ResponseBodyList(resp, body['floating_ip_info'])
+
+ def delete_floating_ips_bulk(self, ip_range):
+ """Deletes the provided floating IPs bulk."""
+ post_body = json.dumps({'ip_range': ip_range})
+ resp, body = self.put('os-floating-ips-bulk/delete', post_body)
+ body = json.loads(body)
+ self.validate_response(schema.delete_floating_ips_bulk, resp, body)
+ data = body['floating_ips_bulk_delete']
+ return service_client.ResponseBodyData(resp, data)
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index 420037b..1a32861 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -99,44 +99,3 @@
def resource_type(self):
"""Returns the primary type of resource this client works with."""
return 'floating_ip'
-
- def list_floating_ip_pools(self, params=None):
- """Returns a list of all floating IP Pools."""
- url = 'os-floating-ip-pools'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_floating_ip_pools, resp, body)
- return service_client.ResponseBodyList(resp, body['floating_ip_pools'])
-
- def create_floating_ips_bulk(self, ip_range, pool, interface):
- """Allocate floating IPs in bulk."""
- post_body = {
- 'ip_range': ip_range,
- 'pool': pool,
- 'interface': interface
- }
- post_body = json.dumps({'floating_ips_bulk_create': post_body})
- resp, body = self.post('os-floating-ips-bulk', post_body)
- body = json.loads(body)
- self.validate_response(schema.create_floating_ips_bulk, resp, body)
- return service_client.ResponseBody(resp,
- body['floating_ips_bulk_create'])
-
- def list_floating_ips_bulk(self):
- """Returns a list of all floating IPs bulk."""
- resp, body = self.get('os-floating-ips-bulk')
- body = json.loads(body)
- self.validate_response(schema.list_floating_ips_bulk, resp, body)
- return service_client.ResponseBodyList(resp, body['floating_ip_info'])
-
- def delete_floating_ips_bulk(self, ip_range):
- """Deletes the provided floating IPs bulk."""
- post_body = json.dumps({'ip_range': ip_range})
- resp, body = self.put('os-floating-ips-bulk/delete', post_body)
- body = json.loads(body)
- self.validate_response(schema.delete_floating_ips_bulk, resp, body)
- data = body['floating_ips_bulk_delete']
- return service_client.ResponseBodyData(resp, data)
diff --git a/tempest/services/compute/json/hypervisor_client.py b/tempest/services/compute/json/hypervisor_client.py
index 865c5bc..61a4dc1 100644
--- a/tempest/services/compute/json/hypervisor_client.py
+++ b/tempest/services/compute/json/hypervisor_client.py
@@ -34,16 +34,16 @@
self.validate_response(_schema, resp, body)
return service_client.ResponseBodyList(resp, body['hypervisors'])
- def show_hypervisor(self, hyper_id):
+ def show_hypervisor(self, hypervisor_id):
"""Display the details of the specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s' % hyper_id)
+ resp, body = self.get('os-hypervisors/%s' % hypervisor_id)
body = json.loads(body)
self.validate_response(schema.get_hypervisor, resp, body)
return service_client.ResponseBody(resp, body['hypervisor'])
- def list_servers_on_hypervisor(self, hyper_name):
+ def list_servers_on_hypervisor(self, hypervisor_name):
"""List instances belonging to the specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s/servers' % hyper_name)
+ resp, body = self.get('os-hypervisors/%s/servers' % hypervisor_name)
body = json.loads(body)
self.validate_response(schema.get_hypervisors_servers, resp, body)
return service_client.ResponseBodyList(resp, body['hypervisors'])
@@ -55,16 +55,16 @@
self.validate_response(schema.get_hypervisor_statistics, resp, body)
return service_client.ResponseBody(resp, body['hypervisor_statistics'])
- def show_hypervisor_uptime(self, hyper_id):
+ def show_hypervisor_uptime(self, hypervisor_id):
"""Display the uptime of the specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s/uptime' % hyper_id)
+ resp, body = self.get('os-hypervisors/%s/uptime' % hypervisor_id)
body = json.loads(body)
self.validate_response(schema.get_hypervisor_uptime, resp, body)
return service_client.ResponseBody(resp, body['hypervisor'])
- def search_hypervisor(self, hyper_name):
+ def search_hypervisor(self, hypervisor_name):
"""Search specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s/search' % hyper_name)
+ resp, body = self.get('os-hypervisors/%s/search' % hypervisor_name)
body = json.loads(body)
self.validate_response(schema.list_search_hypervisors, resp, body)
return service_client.ResponseBodyList(resp, body['hypervisors'])
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index 0e0ff47..e5ab965 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -22,14 +22,14 @@
class InterfacesClient(service_client.ServiceClient):
- def list_interfaces(self, server):
- resp, body = self.get('servers/%s/os-interface' % server)
+ def list_interfaces(self, server_id):
+ resp, body = self.get('servers/%s/os-interface' % server_id)
body = json.loads(body)
self.validate_response(schema.list_interfaces, resp, body)
return service_client.ResponseBodyList(resp,
body['interfaceAttachments'])
- def create_interface(self, server, port_id=None, network_id=None,
+ def create_interface(self, server_id, port_id=None, network_id=None,
fixed_ip=None):
post_body = dict(interfaceAttachment=dict())
if port_id:
@@ -40,20 +40,21 @@
fip = dict(ip_address=fixed_ip)
post_body['interfaceAttachment']['fixed_ips'] = [fip]
post_body = json.dumps(post_body)
- resp, body = self.post('servers/%s/os-interface' % server,
+ resp, body = self.post('servers/%s/os-interface' % server_id,
body=post_body)
body = json.loads(body)
self.validate_response(schema.get_create_interfaces, resp, body)
return service_client.ResponseBody(resp, body['interfaceAttachment'])
- def show_interface(self, server, port_id):
- resp, body = self.get('servers/%s/os-interface/%s' % (server, port_id))
+ def show_interface(self, server_id, port_id):
+ resp, body = self.get('servers/%s/os-interface/%s' % (server_id,
+ port_id))
body = json.loads(body)
self.validate_response(schema.get_create_interfaces, resp, body)
return service_client.ResponseBody(resp, body['interfaceAttachment'])
- def delete_interface(self, server, port_id):
- resp, body = self.delete('servers/%s/os-interface/%s' % (server,
+ def delete_interface(self, server_id, port_id):
+ resp, body = self.delete('servers/%s/os-interface/%s' % (server_id,
port_id))
self.validate_response(schema.delete_interface, resp, body)
return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/keypairs_client.py b/tempest/services/compute/json/keypairs_client.py
index ba8b1e2..cf03a24 100644
--- a/tempest/services/compute/json/keypairs_client.py
+++ b/tempest/services/compute/json/keypairs_client.py
@@ -32,8 +32,8 @@
self.validate_response(schema.list_keypairs, resp, body)
return service_client.ResponseBodyList(resp, body['keypairs'])
- def show_keypair(self, key_name):
- resp, body = self.get("os-keypairs/%s" % key_name)
+ def show_keypair(self, keypair_name):
+ resp, body = self.get("os-keypairs/%s" % keypair_name)
body = json.loads(body)
self.validate_response(schema.get_keypair, resp, body)
return service_client.ResponseBody(resp, body['keypair'])
@@ -48,7 +48,7 @@
self.validate_response(schema.create_keypair, resp, body)
return service_client.ResponseBody(resp, body['keypair'])
- def delete_keypair(self, key_name):
- resp, body = self.delete("os-keypairs/%s" % key_name)
+ def delete_keypair(self, keypair_name):
+ resp, body = self.delete("os-keypairs/%s" % keypair_name)
self.validate_response(schema.delete_keypair, resp, body)
return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/server_groups_client.py b/tempest/services/compute/json/server_groups_client.py
new file mode 100644
index 0000000..9fec930
--- /dev/null
+++ b/tempest/services/compute/json/server_groups_client.py
@@ -0,0 +1,61 @@
+# Copyright 2012 OpenStack Foundation
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
+# 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 json
+
+from tempest.api_schema.response.compute.v2_1 import servers as schema
+from tempest.common import service_client
+
+
+class ServerGroupsClient(service_client.ServiceClient):
+
+ def create_server_group(self, name, policies):
+ """
+ Create the server group
+ name : Name of the server-group
+ policies : List of the policies - affinity/anti-affinity)
+ """
+ post_body = {
+ 'name': name,
+ 'policies': policies,
+ }
+
+ post_body = json.dumps({'server_group': post_body})
+ resp, body = self.post('os-server-groups', post_body)
+
+ body = json.loads(body)
+ self.validate_response(schema.create_get_server_group, resp, body)
+ return service_client.ResponseBody(resp, body['server_group'])
+
+ def delete_server_group(self, server_group_id):
+ """Delete the given server-group."""
+ resp, body = self.delete("os-server-groups/%s" % server_group_id)
+ self.validate_response(schema.delete_server_group, resp, body)
+ return service_client.ResponseBody(resp, body)
+
+ def list_server_groups(self):
+ """List the server-groups."""
+ resp, body = self.get("os-server-groups")
+ body = json.loads(body)
+ self.validate_response(schema.list_server_groups, resp, body)
+ return service_client.ResponseBodyList(resp, body['server_groups'])
+
+ def get_server_group(self, server_group_id):
+ """Get the details of given server_group."""
+ resp, body = self.get("os-server-groups/%s" % server_group_id)
+ body = json.loads(body)
+ self.validate_response(schema.create_get_server_group, resp, body)
+ return service_client.ResponseBody(resp, body['server_group'])
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 2ecb2d4..1a3864c 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -149,28 +149,21 @@
self.validate_response(schema.delete_server, resp, body)
return service_client.ResponseBody(resp, body)
- def list_servers(self, params=None):
+ def list_servers(self, detail=False, **params):
"""Lists all servers for a user."""
url = 'servers'
+ _schema = schema.list_servers
+
+ if detail:
+ url += '/detail'
+ _schema = schema.list_servers_detail
if params:
url += '?%s' % urllib.urlencode(params)
resp, body = self.get(url)
body = json.loads(body)
- self.validate_response(schema.list_servers, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def list_servers_with_detail(self, params=None):
- """Lists all servers in detail for a user."""
-
- url = 'servers/detail'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_servers_detail, resp, body)
+ self.validate_response(_schema, resp, body)
return service_client.ResponseBody(resp, body)
def wait_for_server_status(self, server_id, status, extra_timeout=0,
@@ -532,41 +525,3 @@
return self.action(server_id, "os-getVNCConsole",
"console", schema.get_vnc_console,
type=console_type)
-
- def create_server_group(self, name, policies):
- """
- Create the server group
- name : Name of the server-group
- policies : List of the policies - affinity/anti-affinity)
- """
- post_body = {
- 'name': name,
- 'policies': policies,
- }
-
- post_body = json.dumps({'server_group': post_body})
- resp, body = self.post('os-server-groups', post_body)
-
- body = json.loads(body)
- self.validate_response(schema.create_get_server_group, resp, body)
- return service_client.ResponseBody(resp, body['server_group'])
-
- def delete_server_group(self, server_group_id):
- """Delete the given server-group."""
- resp, body = self.delete("os-server-groups/%s" % server_group_id)
- self.validate_response(schema.delete_server_group, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def list_server_groups(self):
- """List the server-groups."""
- resp, body = self.get("os-server-groups")
- body = json.loads(body)
- self.validate_response(schema.list_server_groups, resp, body)
- return service_client.ResponseBodyList(resp, body['server_groups'])
-
- def get_server_group(self, server_group_id):
- """Get the details of given server_group."""
- resp, body = self.get("os-server-groups/%s" % server_group_id)
- body = json.loads(body)
- self.validate_response(schema.create_get_server_group, resp, body)
- return service_client.ResponseBody(resp, body['server_group'])
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 13449ea..b3663fc 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -73,17 +73,14 @@
}
return resource_plural_map.get(resource_name, resource_name + 's')
- def _lister(self, plural_name):
- def _list(**filters):
- uri = self.get_uri(plural_name)
- if filters:
- uri += '?' + urllib.urlencode(filters, doseq=1)
- resp, body = self.get(uri)
- result = {plural_name: self.deserialize_list(body)}
- self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, result)
-
- return _list
+ def _list_resources(self, uri, **filters):
+ req_uri = self.uri_prefix + uri
+ if filters:
+ req_uri += '?' + urllib.urlencode(filters, doseq=1)
+ resp, body = self.get(req_uri)
+ body = self.deserialize_list(body)
+ self.expected_success(200, resp.status)
+ return service_client.ResponseBody(resp, body)
def _delete_resource(self, uri):
req_uri = self.uri_prefix + uri
@@ -119,15 +116,6 @@
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
- def __getattr__(self, name):
- method_prefixes = ["list_"]
- method_functors = [self._lister]
- for index, prefix in enumerate(method_prefixes):
- prefix_len = len(prefix)
- if name[:prefix_len] == prefix:
- return method_functors[index](name[prefix_len:])
- raise AttributeError(name)
-
def create_network(self, **kwargs):
uri = '/networks'
post_data = {'network': kwargs}
@@ -146,6 +134,10 @@
uri = '/networks/%s' % network_id
return self._delete_resource(uri)
+ def list_networks(self, **filters):
+ uri = '/networks'
+ return self._list_resources(uri, **filters)
+
def create_subnet(self, **kwargs):
uri = '/subnets'
post_data = {'subnet': kwargs}
@@ -164,6 +156,10 @@
uri = '/subnets/%s' % subnet_id
return self._delete_resource(uri)
+ def list_subnets(self, **filters):
+ uri = '/subnets'
+ return self._list_resources(uri, **filters)
+
def create_port(self, **kwargs):
uri = '/ports'
post_data = {'port': kwargs}
@@ -182,6 +178,10 @@
uri = '/ports/%s' % port_id
return self._delete_resource(uri)
+ def list_ports(self, **filters):
+ uri = '/ports'
+ return self._list_resources(uri, **filters)
+
def create_floatingip(self, **kwargs):
uri = '/floatingips'
post_data = {'floatingip': kwargs}
@@ -200,6 +200,10 @@
uri = '/floatingips/%s' % floatingip_id
return self._delete_resource(uri)
+ def list_floatingips(self, **filters):
+ uri = '/floatingips'
+ return self._list_resources(uri, **filters)
+
def create_metering_label(self, **kwargs):
uri = '/metering/metering-labels'
post_data = {'metering_label': kwargs}
@@ -213,6 +217,10 @@
uri = '/metering/metering-labels/%s' % metering_label_id
return self._delete_resource(uri)
+ def list_metering_labels(self, **filters):
+ uri = '/metering/metering-labels'
+ return self._list_resources(uri, **filters)
+
def create_metering_label_rule(self, **kwargs):
uri = '/metering/metering-label-rules'
post_data = {'metering_label_rule': kwargs}
@@ -226,6 +234,10 @@
uri = '/metering/metering-label-rules/%s' % metering_label_rule_id
return self._delete_resource(uri)
+ def list_metering_label_rules(self, **filters):
+ uri = '/metering/metering-label-rules'
+ return self._list_resources(uri, **filters)
+
def create_security_group(self, **kwargs):
uri = '/security-groups'
post_data = {'security_group': kwargs}
@@ -244,6 +256,10 @@
uri = '/security-groups/%s' % security_group_id
return self._delete_resource(uri)
+ def list_security_groups(self, **filters):
+ uri = '/security-groups'
+ return self._list_resources(uri, **filters)
+
def create_security_group_rule(self, **kwargs):
uri = '/security-group-rules'
post_data = {'security_group_rule': kwargs}
@@ -257,10 +273,18 @@
uri = '/security-group-rules/%s' % security_group_rule_id
return self._delete_resource(uri)
+ def list_security_group_rules(self, **filters):
+ uri = '/security-group-rules'
+ return self._list_resources(uri, **filters)
+
def show_extension(self, ext_alias, **fields):
uri = '/extensions/%s' % ext_alias
return self._show_resource(uri, **fields)
+ def list_extensions(self, **filters):
+ uri = '/extensions'
+ return self._list_resources(uri, **filters)
+
# Common methods that are hard to automate
def create_bulk_network(self, names):
network_list = [{'name': name} for name in names]
@@ -268,7 +292,7 @@
body = self.serialize_list(post_data, "networks", "network")
uri = self.get_uri("networks")
resp, body = self.post(uri, body)
- body = {'networks': self.deserialize_list(body)}
+ body = self.deserialize_list(body)
self.expected_success(201, resp.status)
return service_client.ResponseBody(resp, body)
@@ -277,7 +301,7 @@
body = self.serialize_list(post_data, 'subnets', 'subnet')
uri = self.get_uri('subnets')
resp, body = self.post(uri, body)
- body = {'subnets': self.deserialize_list(body)}
+ body = self.deserialize_list(body)
self.expected_success(201, resp.status)
return service_client.ResponseBody(resp, body)
@@ -286,7 +310,7 @@
body = self.serialize_list(post_data, 'ports', 'port')
uri = self.get_uri('ports')
resp, body = self.post(uri, body)
- body = {'ports': self.deserialize_list(body)}
+ body = self.deserialize_list(body)
self.expected_success(201, resp.status)
return service_client.ResponseBody(resp, body)
@@ -351,14 +375,7 @@
return json.loads(body)
def deserialize_list(self, body):
- res = json.loads(body)
- # expecting response in form
- # {'resources': [ res1, res2] } => when pagination disabled
- # {'resources': [..], 'resources_links': {}} => if pagination enabled
- for k in res.keys():
- if k.endswith("_links"):
- continue
- return res[k]
+ return json.loads(body)
def serialize(self, data):
return json.dumps(data)
@@ -385,6 +402,10 @@
uri = '/quotas/%s' % tenant_id
return self._show_resource(uri, **fields)
+ def list_quotas(self, **filters):
+ uri = '/quotas'
+ return self._list_resources(uri, **filters)
+
def create_router(self, name, admin_state_up=True, **kwargs):
post_body = {'router': kwargs}
post_body['router']['name'] = name
@@ -442,6 +463,10 @@
uri = '/routers/%s' % router_id
return self._delete_resource(uri)
+ def list_routers(self, **filters):
+ uri = '/routers'
+ return self._list_resources(uri, **filters)
+
def update_router_with_snat_gw_info(self, router_id, **kwargs):
"""Update a router passing also the enable_snat attribute.
@@ -514,6 +539,10 @@
uri = '/agents/%s' % agent_id
return self._show_resource(uri, **fields)
+ def list_agents(self, **filters):
+ uri = '/agents'
+ return self._list_resources(uri, **filters)
+
def list_routers_on_l3_agent(self, agent_id):
uri = '%s/agents/%s/l3-routers' % (self.uri_prefix, agent_id)
resp, body = self.get(uri)
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index 466e225..b8e3464 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -15,6 +15,7 @@
import json
+import six
from six.moves.urllib import parse as urllib
from tempest_lib import exceptions as lib_exc
@@ -39,18 +40,57 @@
"""Return the element 'attachment' from input volumes."""
return volume['attachments'][0]
- def list_volumes(self, detail=False, params=None):
- """List all the volumes created."""
+ def _ext_get(self, url, key=None, status=200):
+ """Extended get method.
+
+ Retrieves requested url, checks that status is expected status and
+ return a ResponseBody, ResponseBodyList or ResponseBodyData depending
+ on received data's key entry.
+
+ If key is not specified or is None we will return the whole body in a
+ ResponseBody class.
+ """
+
+ resp, body = self.get(url)
+ body = json.loads(body)
+ self.expected_success(status, resp.status)
+
+ if not key:
+ return service_client.ResponseBody(resp, body)
+ elif isinstance(body[key], dict):
+ return service_client.ResponseBody(resp, body[key])
+ elif isinstance(body[key], list):
+ return service_client.ResponseBodyList(resp, body[key])
+
+ return service_client.ResponseBodyData(resp, body[key])
+
+ def _prepare_params(self, params):
+ """Prepares params for use in get or _ext_get methods.
+
+ If params is a string it will be left as it is, but if it's not it will
+ be urlencoded.
+ """
+ if isinstance(params, six.string_types):
+ return params
+ return urllib.urlencode(params)
+
+ def list_volumes(self, detail=False, params=None, return_body=False):
+ """List all the volumes created.
+
+ Params can be a string (must be urlencoded) or a dictionary.
+ If return_body is True then we will return the whole response body in
+ a ResponseBody class, it it's False or has not been specified we will
+ return only the list of volumes in a ResponseBodyList (inherits from
+ list).
+ """
url = 'volumes'
if detail:
url += '/detail'
if params:
- url += '?%s' % urllib.urlencode(params)
+ url += '?%s' % self._prepare_params(params)
- resp, body = self.get(url)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return service_client.ResponseBodyList(resp, body['volumes'])
+ key = None if return_body else 'volumes'
+ return self._ext_get(url, key)
def show_volume(self, volume_id):
"""Returns the details of a single volume."""
diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py
index 29c4401..d9b430e 100644
--- a/tempest/stress/cleanup.py
+++ b/tempest/stress/cleanup.py
@@ -24,7 +24,7 @@
def cleanup():
admin_manager = clients.AdminManager()
- body = admin_manager.servers_client.list_servers({"all_tenants": True})
+ body = admin_manager.servers_client.list_servers(all_tenants=True)
LOG.info("Cleanup::remove %s servers" % len(body['servers']))
for s in body['servers']:
try:
diff --git a/tempest/test_discover/plugins.py b/tempest/test_discover/plugins.py
new file mode 100644
index 0000000..197bd0c
--- /dev/null
+++ b/tempest/test_discover/plugins.py
@@ -0,0 +1,56 @@
+# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
+#
+# 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 abc
+
+import six
+import stevedore
+from tempest_lib.common.utils import misc
+
+
+@six.add_metaclass(abc.ABCMeta)
+class TempestPlugin(object):
+ """A TempestPlugin class provides the basic hooks for an external
+ plugin to provide tempest the necessary information to run the plugin.
+ """
+
+ @abc.abstractmethod
+ def load_tests(self):
+ """Method to return the information necessary to load the tests in the
+ plugin.
+
+ :return: a tuple with the first value being the test_dir and the second
+ being the top_level
+ :rtype: tuple
+ """
+ return
+
+
+@misc.singleton
+class TempestTestPluginManager(object):
+ """Tempest test plugin manager class
+
+ This class is used to manage the lifecycle of external tempest test
+ plugins. It provides functions for getting set
+ """
+ def __init__(self):
+ self.ext_plugins = stevedore.ExtensionManager(
+ 'tempest.test.plugins', invoke_on_load=True,
+ propagate_map_exceptions=True)
+
+ def get_plugin_load_tests_tuple(self):
+ load_tests_dict = {}
+ for plug in self.ext_plugins:
+ load_tests_dict[plug.name] = plug.obj.load_tests()
+ return load_tests_dict
diff --git a/tempest/test_discover/test_discover.py b/tempest/test_discover/test_discover.py
index 4a4b43a..86aa855 100644
--- a/tempest/test_discover/test_discover.py
+++ b/tempest/test_discover/test_discover.py
@@ -15,6 +15,8 @@
import os
import sys
+from tempest.test_discover import plugins
+
if sys.version_info >= (2, 7):
import unittest
else:
@@ -22,14 +24,32 @@
def load_tests(loader, tests, pattern):
+ ext_plugins = plugins.TempestTestPluginManager()
+
suite = unittest.TestSuite()
base_path = os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]
base_path = os.path.split(base_path)[0]
- for test_dir in ['./tempest/api', './tempest/scenario',
- './tempest/thirdparty']:
+ # Load local tempest tests
+ for test_dir in ['tempest/api', 'tempest/scenario',
+ 'tempest/thirdparty']:
+ full_test_dir = os.path.join(base_path, test_dir)
if not pattern:
- suite.addTests(loader.discover(test_dir, top_level_dir=base_path))
+ suite.addTests(loader.discover(full_test_dir,
+ top_level_dir=base_path))
+ else:
+ suite.addTests(loader.discover(full_test_dir, pattern=pattern,
+ top_level_dir=base_path))
+
+ plugin_load_tests = ext_plugins.get_plugin_load_tests_tuple()
+ if not plugin_load_tests:
+ return suite
+
+ # Load any installed plugin tests
+ for plugin in plugin_load_tests:
+ test_dir, top_path = plugin_load_tests[plugin]
+ if not pattern:
+ suite.addTests(loader.discover(test_dir, top_level=top_path))
else:
suite.addTests(loader.discover(test_dir, pattern=pattern,
- top_level_dir=base_path))
+ top_level=top_path))
return suite
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
index 3de7aba..695d4a4 100644
--- a/tempest/tests/common/test_service_clients.py
+++ b/tempest/tests/common/test_service_clients.py
@@ -24,6 +24,8 @@
from tempest.services.compute.json import extensions_client
from tempest.services.compute.json import fixed_ips_client
from tempest.services.compute.json import flavors_client
+from tempest.services.compute.json import floating_ip_pools_client
+from tempest.services.compute.json import floating_ips_bulk_client
from tempest.services.compute.json import floating_ips_client
from tempest.services.compute.json import hosts_client
from tempest.services.compute.json import hypervisor_client
@@ -39,6 +41,7 @@
from tempest.services.compute.json import security_group_default_rules_client \
as nova_secgrop_default_client
from tempest.services.compute.json import security_groups_client
+from tempest.services.compute.json import server_groups_client
from tempest.services.compute.json import servers_client
from tempest.services.compute.json import services_client
from tempest.services.compute.json import tenant_usages_client
@@ -112,6 +115,8 @@
extensions_client.ExtensionsClient,
fixed_ips_client.FixedIPsClient,
flavors_client.FlavorsClient,
+ floating_ip_pools_client.FloatingIpPoolsClient,
+ floating_ips_bulk_client.FloatingIpsBulkClient,
floating_ips_client.FloatingIPsClient,
hosts_client.HostsClient,
hypervisor_client.HypervisorClient,
@@ -126,6 +131,7 @@
quota_classes_client.QuotaClassesClient,
nova_secgrop_default_client.SecurityGroupDefaultRulesClient,
security_groups_client.SecurityGroupsClient,
+ server_groups_client.ServerGroupsClient,
servers_client.ServersClient,
services_client.ServicesClient,
tenant_usages_client.TenantUsagesClient,
diff --git a/tempest/tests/test_glance_http.py b/tempest/tests/test_glance_http.py
index 7850ee4..71aa395 100644
--- a/tempest/tests/test_glance_http.py
+++ b/tempest/tests/test_glance_http.py
@@ -137,7 +137,8 @@
resp, body = self.client.raw_request('PUT', '/images', body=req_body)
self.assertEqual(200, resp.status)
self.assertEqual('fake_response_body', body.read())
- httplib.HTTPConnection.send.assert_call_count(req_body.tell())
+ call_count = httplib.HTTPConnection.send.call_count
+ self.assertEqual(call_count - 1, req_body.tell())
def test_get_connection_class_for_https(self):
conn_class = self.client.get_connection_class('https')
diff --git a/test-requirements.txt b/test-requirements.txt
index 9bd3f46..7115168 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -7,7 +7,7 @@
python-subunit>=0.0.18
oslosphinx>=2.5.0 # Apache-2.0
mox>=0.5.3
-mock>=1.0
+mock>=1.1;python_version!='2.6'
+mock==1.0.1;python_version=='2.6'
coverage>=3.6
oslotest>=1.5.1 # Apache-2.0
-stevedore>=1.5.0 # Apache-2.0
diff --git a/tools/install_venv.py b/tools/install_venv.py
index 96b8279..d6d9c8e 100644
--- a/tools/install_venv.py
+++ b/tools/install_venv.py
@@ -48,11 +48,11 @@
def main(argv):
root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
- if os.environ.get('tools_path'):
- root = os.environ['tools_path']
+ if os.environ.get('TOOLS_PATH'):
+ root = os.environ['TOOLS_PATH']
venv = os.path.join(root, '.venv')
- if os.environ.get('venv'):
- venv = os.environ['venv']
+ if os.environ.get('VENV'):
+ venv = os.environ['VENV']
pip_requires = os.path.join(root, 'requirements.txt')
test_requires = os.path.join(root, 'test-requirements.txt')
diff --git a/tools/install_venv_common.py b/tools/install_venv_common.py
index 743b59d..e279159 100644
--- a/tools/install_venv_common.py
+++ b/tools/install_venv_common.py
@@ -101,6 +101,7 @@
print('done.')
else:
print("venv already exists...")
+ pass
def pip_install(self, *args):
self.run_command(['tools/with_venv.sh',
@@ -124,7 +125,7 @@
parser.add_option('-n', '--no-site-packages',
action='store_true',
help="Do not inherit packages from global Python "
- "install")
+ "install.")
return parser.parse_args(argv[1:])[0]
diff --git a/tools/with_venv.sh b/tools/with_venv.sh
index 550c477..165c883 100755
--- a/tools/with_venv.sh
+++ b/tools/with_venv.sh
@@ -1,4 +1,6 @@
#!/bin/bash
-TOOLS=`dirname $0`
-VENV=$TOOLS/../.venv
-source $VENV/bin/activate && "$@"
+TOOLS_PATH=${TOOLS_PATH:-$(dirname $0)/../}
+VENV_PATH=${VENV_PATH:-${TOOLS_PATH}}
+VENV_DIR=${VENV_DIR:-/.venv}
+VENV=${VENV:-${VENV_PATH}/${VENV_DIR}}
+source ${VENV}/bin/activate && "$@"