Merge "Merge wait_for_volume_status to common method"
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/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/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 8b0e1a4..ea5f142 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)
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/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/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_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/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_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/servers_client.py b/tempest/services/compute/json/servers_client.py
index 2ecb2d4..7263014 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,
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 13449ea..a903457 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -79,9 +79,9 @@
if filters:
uri += '?' + urllib.urlencode(filters, doseq=1)
resp, body = self.get(uri)
- result = {plural_name: self.deserialize_list(body)}
+ body = self.deserialize_list(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, result)
+ return service_client.ResponseBody(resp, body)
return _list
@@ -268,7 +268,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 +277,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 +286,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 +351,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)
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..a871d10 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,9 +24,12 @@
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]
+ # Load local tempest tests
for test_dir in ['./tempest/api', './tempest/scenario',
'./tempest/thirdparty']:
if not pattern:
@@ -32,4 +37,17 @@
else:
suite.addTests(loader.discover(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=top_path))
return suite
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..2b3607d 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -10,4 +10,3 @@
mock>=1.0
coverage>=3.6
oslotest>=1.5.1 # Apache-2.0
-stevedore>=1.5.0 # Apache-2.0