Merge "Use python abc in DeletableResource class"
diff --git a/etc/schemas/compute/admin/flavor_create.json b/etc/schemas/compute/admin/flavor_create.json
deleted file mode 100644
index 0a3e7b3..0000000
--- a/etc/schemas/compute/admin/flavor_create.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "flavor-create",
- "http-method": "POST",
- "admin_client": true,
- "url": "flavors",
- "default_result_code": 400,
- "json-schema": {
- "type": "object",
- "properties": {
- "name": { "type": "string"},
- "ram": { "type": "integer", "minimum": 1},
- "vcpus": { "type": "integer", "minimum": 1},
- "disk": { "type": "integer"},
- "id": { "type": "integer"},
- "swap": { "type": "integer"},
- "rxtx_factor": { "type": "integer"},
- "OS-FLV-EXT-DATA:ephemeral": { "type": "integer"}
- }
- }
-}
diff --git a/etc/schemas/compute/flavors/flavor_details.json b/etc/schemas/compute/flavors/flavor_details.json
deleted file mode 100644
index c16075c..0000000
--- a/etc/schemas/compute/flavors/flavor_details.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "get-flavor-details",
- "http-method": "GET",
- "url": "flavors/%s",
- "resources": [
- {"name": "flavor", "expected_result": 404}
- ]
-}
diff --git a/etc/schemas/compute/flavors/flavor_details_v3.json b/etc/schemas/compute/flavors/flavor_details_v3.json
deleted file mode 100644
index d1c1077..0000000
--- a/etc/schemas/compute/flavors/flavor_details_v3.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "get-flavor-details",
- "http-method": "GET",
- "url": "flavors/%s",
- "resources": ["flavor"]
-}
diff --git a/etc/schemas/compute/flavors/flavors_list.json b/etc/schemas/compute/flavors/flavors_list.json
deleted file mode 100644
index eb8383b..0000000
--- a/etc/schemas/compute/flavors/flavors_list.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "name": "list-flavors-with-detail",
- "http-method": "GET",
- "url": "flavors/detail",
- "json-schema": {
- "type": "object",
- "properties": {
- "minRam": {
- "type": "integer",
- "results": {
- "gen_none": 400,
- "gen_string": 400
- }
- },
- "minDisk": {
- "type": "integer",
- "results": {
- "gen_none": 400,
- "gen_string": 400
- }
- }
- }
- }
-}
diff --git a/etc/schemas/compute/flavors/flavors_list_v3.json b/etc/schemas/compute/flavors/flavors_list_v3.json
deleted file mode 100644
index d5388b3..0000000
--- a/etc/schemas/compute/flavors/flavors_list_v3.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "name": "list-flavors-with-detail",
- "http-method": "GET",
- "url": "flavors/detail",
- "json-schema": {
- "type": "object",
- "properties": {
- "min_ram": {
- "type": "integer",
- "results": {
- "gen_none": 400,
- "gen_string": 400
- }
- },
- "min_disk": {
- "type": "integer",
- "results": {
- "gen_none": 400,
- "gen_string": 400
- }
- }
- }
- }
-}
diff --git a/etc/schemas/compute/servers/get_console_output.json b/etc/schemas/compute/servers/get_console_output.json
deleted file mode 100644
index 8d974ba..0000000
--- a/etc/schemas/compute/servers/get_console_output.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "name": "get-console-output",
- "http-method": "POST",
- "url": "servers/%s/action",
- "resources": [
- {"name":"server", "expected_result": 404}
- ],
- "json-schema": {
- "type": "object",
- "properties": {
- "os-getConsoleOutput": {
- "type": "object",
- "properties": {
- "length": {
- "type": ["integer", "string"],
- "minimum": 0
- }
- }
- }
- },
- "additionalProperties": false
- }
-}
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 9ace4ea..247f6d1 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -474,6 +474,10 @@
# attachment? (boolean value)
#interface_attach=true
+# Does the test environment support creating snapshot images
+# of running instances? (boolean value)
+#snapshot=true
+
[dashboard]
diff --git a/tempest/api/compute/admin/test_flavors_negative.py b/tempest/api/compute/admin/test_flavors_negative.py
index 9e4412f..eece096 100644
--- a/tempest/api/compute/admin/test_flavors_negative.py
+++ b/tempest/api/compute/admin/test_flavors_negative.py
@@ -16,6 +16,7 @@
import uuid
from tempest.api.compute import base
+from tempest.api_schema.request.compute.v2 import flavors
from tempest.common.utils import data_utils
from tempest import exceptions
from tempest import test
@@ -106,4 +107,4 @@
test.NegativeAutoTest):
_interface = 'json'
_service = 'compute'
- _schema_file = 'compute/admin/flavor_create.json'
+ _schema = flavors.flavor_create
diff --git a/tempest/api/compute/admin/test_networks.py b/tempest/api/compute/admin/test_networks.py
new file mode 100644
index 0000000..032e2f5
--- /dev/null
+++ b/tempest/api/compute/admin/test_networks.py
@@ -0,0 +1,52 @@
+# Copyright 2014 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.
+
+from tempest.api.compute import base
+from tempest import config
+
+CONF = config.CONF
+
+
+class NetworksTest(base.BaseComputeAdminTest):
+ _api_version = 2
+
+ """
+ Tests Nova Networks API that usually requires admin privileges.
+ API docs:
+ http://developer.openstack.org/api-ref-compute-v2-ext.html#ext-os-networks
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ super(NetworksTest, cls).setUpClass()
+ cls.client = cls.os_adm.networks_client
+
+ def test_get_network(self):
+ resp, networks = self.client.list_networks()
+ configured_network = [x for x in networks if x['label'] ==
+ CONF.compute.fixed_network_name]
+ self.assertEqual(1, len(configured_network),
+ "{0} networks with label {1}".format(
+ len(configured_network),
+ CONF.compute.fixed_network_name))
+ configured_network = configured_network[0]
+ _, network = self.client.get_network(configured_network['id'])
+ self.assertEqual(configured_network['label'], network['label'])
+
+ def test_list_all_networks(self):
+ _, networks = self.client.list_networks()
+ # Check the configured network is in the list
+ configured_network = CONF.compute.fixed_network_name
+ self.assertIn(configured_network, [x['label'] for x in networks])
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 599b058..4afda03 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -94,6 +94,7 @@
@test.skip_because(bug="1186354",
condition=CONF.service_available.neutron)
@test.attr(type='gate')
+ @test.services('network')
def test_security_groups_exceed_limit(self):
# Negative test: Creation Security Groups over limit should FAIL
@@ -120,6 +121,7 @@
@test.skip_because(bug="1186354",
condition=CONF.service_available.neutron)
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_security_groups_rules_exceed_limit(self):
# Negative test: Creation of Security Group Rules should FAIL
# when we reach limit maxSecurityGroupRules
diff --git a/tempest/api/compute/admin/test_security_group_default_rules.py b/tempest/api/compute/admin/test_security_group_default_rules.py
index 07408a8..a07d270 100644
--- a/tempest/api/compute/admin/test_security_group_default_rules.py
+++ b/tempest/api/compute/admin/test_security_group_default_rules.py
@@ -55,7 +55,7 @@
@test.attr(type='smoke')
def test_create_delete_security_group_default_rules(self):
# Create and delete Security Group default rule
- ip_protocols = {'tcp', 'udp', 'icmp'}
+ ip_protocols = ['tcp', 'udp', 'icmp']
for ip_protocol in ip_protocols:
rule = self._create_security_group_default_rules(ip_protocol)
# Delete Security Group default rule
diff --git a/tempest/api/compute/flavors/test_flavors_negative.py b/tempest/api/compute/flavors/test_flavors_negative.py
index 1638f2d..7672fc6 100644
--- a/tempest/api/compute/flavors/test_flavors_negative.py
+++ b/tempest/api/compute/flavors/test_flavors_negative.py
@@ -13,8 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-
from tempest.api.compute import base
+from tempest.api_schema.request.compute.v2 import flavors
from tempest import test
@@ -25,14 +25,14 @@
class FlavorsListWithDetailsNegativeTestJSON(base.BaseV2ComputeTest,
test.NegativeAutoTest):
_service = 'compute'
- _schema_file = 'compute/flavors/flavors_list.json'
+ _schema = flavors.flavor_list
@test.SimpleNegativeAutoTest
class FlavorDetailsNegativeTestJSON(base.BaseV2ComputeTest,
test.NegativeAutoTest):
_service = 'compute'
- _schema_file = 'compute/flavors/flavor_details.json'
+ _schema = flavors.flavors_details
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index 29df2b0..bbb887f 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -28,6 +28,12 @@
if not CONF.service_available.glance:
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
raise cls.skipException(skip_msg)
+
+ if not CONF.compute_feature_enabled.snapshot:
+ skip_msg = ("%s skipped as instance snapshotting is not supported"
+ % cls.__name__)
+ raise cls.skipException(skip_msg)
+
cls.client = cls.images_client
cls.servers_client = cls.servers_client
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index 6163f4d..771040b 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -29,6 +29,12 @@
if not CONF.service_available.glance:
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
raise cls.skipException(skip_msg)
+
+ if not CONF.compute_feature_enabled.snapshot:
+ skip_msg = ("%s skipped as instance snapshotting is not supported"
+ % cls.__name__)
+ raise cls.skipException(skip_msg)
+
cls.client = cls.images_client
cls.servers_client = cls.servers_client
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index c81cec5..187c0d4 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -54,6 +54,11 @@
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
raise cls.skipException(skip_msg)
+ if not CONF.compute_feature_enabled.snapshot:
+ skip_msg = ("%s skipped as instance snapshotting is not supported"
+ % cls.__name__)
+ raise cls.skipException(skip_msg)
+
try:
resp, server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index 9c4ab00..4e84e08 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -62,6 +62,11 @@
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
raise cls.skipException(skip_msg)
+ if not CONF.compute_feature_enabled.snapshot:
+ skip_msg = ("%s skipped as instance snapshotting is not supported"
+ % cls.__name__)
+ raise cls.skipException(skip_msg)
+
try:
resp, server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index f9350e1..68794b1 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -16,6 +16,8 @@
import StringIO
import time
+import testtools
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
@@ -63,6 +65,9 @@
cls.image3 = _create_image()
cls.image3_id = cls.image3['id']
+ if not CONF.compute_feature_enabled.snapshot:
+ return
+
# Create instances and snapshots via nova
try:
resp, cls.server1 = cls.create_test_server()
@@ -114,6 +119,8 @@
self.assertFalse(any([i for i in images if i['id'] == self.image2_id]))
self.assertFalse(any([i for i in images if i['id'] == self.image3_id]))
+ @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
+ 'Snapshotting is not available.')
@test.attr(type='gate')
def test_list_images_filter_by_server_id(self):
# The images should contain images filtered by server id
@@ -129,6 +136,8 @@
self.assertFalse(any([i for i in images
if i['id'] == self.snapshot3_id]))
+ @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
+ 'Snapshotting is not available.')
@test.attr(type='gate')
def test_list_images_filter_by_server_ref(self):
# The list of servers should be filtered by server ref
@@ -146,6 +155,8 @@
self.assertTrue(any([i for i in images
if i['id'] == self.snapshot3_id]))
+ @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
+ 'Snapshotting is not available.')
@test.attr(type='gate')
def test_list_images_filter_by_type(self):
# The list of servers should be filtered by image type
@@ -211,6 +222,8 @@
resp, images = self.client.list_images_with_detail(params)
self.assertEqual(1, len(images))
+ @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
+ 'Snapshotting is not available.')
@test.attr(type='gate')
def test_list_images_with_detail_filter_by_server_ref(self):
# Detailed list of servers should be filtered by server ref
@@ -228,6 +241,8 @@
self.assertTrue(any([i for i in images
if i['id'] == self.snapshot3_id]))
+ @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
+ 'Snapshotting is not available.')
@test.attr(type='gate')
def test_list_images_with_detail_filter_by_type(self):
# The detailed list of servers should be filtered by image type
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 005f38a..f684a5a 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -256,6 +256,8 @@
resp, server = self.client.get_server(self.server_id)
self.assertEqual(previous_flavor_ref, server['flavor']['id'])
+ @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
+ 'Snapshotting not available, backup not possible.')
@test.attr(type='gate')
def test_create_backup(self):
# Positive test:create backup successfully and rotate backups correctly
diff --git a/tempest/api/compute/servers/test_servers_negative_new.py b/tempest/api/compute/servers/test_servers_negative_new.py
index 43ddb3a..c5f9fdd 100644
--- a/tempest/api/compute/servers/test_servers_negative_new.py
+++ b/tempest/api/compute/servers/test_servers_negative_new.py
@@ -15,6 +15,7 @@
from tempest.api.compute import base
+from tempest.api_schema.request.compute.v2 import servers
from tempest import test
@@ -25,7 +26,7 @@
class GetConsoleOutputNegativeTestJSON(base.BaseV2ComputeTest,
test.NegativeAutoTest):
_service = 'compute'
- _schema_file = 'compute/servers/get_console_output.json'
+ _schema = servers.get_console_output
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/v3/flavors/test_flavors_negative.py b/tempest/api/compute/v3/flavors/test_flavors_negative.py
index 657e2cd..cdf018f 100644
--- a/tempest/api/compute/v3/flavors/test_flavors_negative.py
+++ b/tempest/api/compute/v3/flavors/test_flavors_negative.py
@@ -14,6 +14,7 @@
# under the License.
from tempest.api.compute import base
+from tempest.api_schema.request.compute.v3 import flavors
from tempest import test
@@ -24,14 +25,14 @@
class FlavorsListNegativeV3Test(base.BaseV3ComputeTest,
test.NegativeAutoTest):
_service = 'computev3'
- _schema_file = 'compute/flavors/flavors_list_v3.json'
+ _schema = flavors.flavor_list
@test.SimpleNegativeAutoTest
class FlavorDetailsNegativeV3Test(base.BaseV3ComputeTest,
test.NegativeAutoTest):
_service = 'computev3'
- _schema_file = 'compute/flavors/flavor_details_v3.json'
+ _schema = flavors.flavors_details
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/v3/servers/test_server_actions.py b/tempest/api/compute/v3/servers/test_server_actions.py
index d05e158..538507f 100644
--- a/tempest/api/compute/v3/servers/test_server_actions.py
+++ b/tempest/api/compute/v3/servers/test_server_actions.py
@@ -250,6 +250,8 @@
resp, server = self.client.get_server(self.server_id)
self.assertEqual(previous_flavor_ref, server['flavor']['id'])
+ @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
+ 'Snapshotting not available, backup not possible.')
@test.attr(type='gate')
def test_create_backup(self):
# Positive test:create backup successfully and rotate backups correctly
diff --git a/tempest/api/orchestration/stacks/test_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py
index d422752..f11ac2a 100644
--- a/tempest/api/orchestration/stacks/test_volumes.py
+++ b/tempest/api/orchestration/stacks/test_volumes.py
@@ -79,8 +79,7 @@
def _cleanup_volume(self, volume_id):
"""Cleanup the volume direct with cinder."""
- resp = self.volumes_client.delete_volume(volume_id)
- self.assertEqual(202, resp[0].status)
+ self.volumes_client.delete_volume(volume_id)
self.volumes_client.wait_for_resource_deletion(volume_id)
@test.attr(type='gate')
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index d451517..f3b1ad5 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -61,11 +61,11 @@
extra_specs = {spec_key_with_prefix: backend_name_key}
else:
extra_specs = {spec_key_without_prefix: backend_name_key}
- resp, self.type = self.client.create_volume_type(
+ _, self.type = self.client.create_volume_type(
type_name, extra_specs=extra_specs)
self.volume_type_id_list.append(self.type['id'])
- resp, self.volume = self.volume_client.create_volume(
+ _, self.volume = self.volume_client.create_volume(
size=1, display_name=vol_name, volume_type=type_name)
self.volume_client.wait_for_volume_status(
self.volume['id'], 'available')
@@ -130,8 +130,7 @@
# the multi backend feature has been enabled
# if multi-backend is enabled: os-vol-attr:host should be like:
# host@backend_name
- resp, volume = self.volume_client.get_volume(volume_id)
- self.assertEqual(200, resp.status)
+ _, volume = self.volume_client.get_volume(volume_id)
volume1_host = volume['os-vol-host-attr:host']
msg = ("multi-backend reporting incorrect values for volume %s" %
@@ -142,10 +141,10 @@
# this test checks that the two volumes created at setUp don't
# belong to the same backend (if they are, than the
# volume backend distinction is not working properly)
- resp, volume = self.volume_client.get_volume(volume1_id)
+ _, volume = self.volume_client.get_volume(volume1_id)
volume1_host = volume['os-vol-host-attr:host']
- resp, volume = self.volume_client.get_volume(volume2_id)
+ _, volume = self.volume_client.get_volume(volume2_id)
volume2_host = volume['os-vol-host-attr:host']
msg = ("volumes %s and %s were created in the same backend" %
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index 594c703..abbe1e9 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -32,14 +32,14 @@
# Create a test shared volume for tests
vol_name = data_utils.rand_name(cls.__name__ + '-Volume-')
- resp_vol, cls.volume = \
+ _, cls.volume = \
cls.volumes_client.create_volume(size=1, display_name=vol_name)
cls.volumes_client.wait_for_volume_status(cls.volume['id'],
'available')
# Create a test shared snapshot for tests
snap_name = data_utils.rand_name(cls.__name__ + '-Snapshot-')
- resp_snap, cls.snapshot = \
+ _, cls.snapshot = \
cls.client.create_snapshot(cls.volume['id'],
display_name=snap_name)
cls.client.wait_for_snapshot_status(cls.snapshot['id'],
@@ -70,12 +70,10 @@
# and force delete temp snapshot
temp_snapshot = self.create_snapshot(self.volume['id'])
if status:
- resp, body = self.admin_snapshots_client.\
+ _, body = self.admin_snapshots_client.\
reset_snapshot_status(temp_snapshot['id'], status)
- self.assertEqual(202, resp.status)
- resp_delete, volume_delete = self.admin_snapshots_client.\
+ _, volume_delete = self.admin_snapshots_client.\
force_delete_snapshot(temp_snapshot['id'])
- self.assertEqual(202, resp_delete.status)
self.client.wait_for_resource_deletion(temp_snapshot['id'])
def _get_progress_alias(self):
@@ -85,12 +83,10 @@
def test_reset_snapshot_status(self):
# Reset snapshot status to creating
status = 'creating'
- resp, body = self.admin_snapshots_client.\
+ _, body = self.admin_snapshots_client.\
reset_snapshot_status(self.snapshot['id'], status)
- self.assertEqual(202, resp.status)
- resp_get, snapshot_get \
+ _, snapshot_get \
= self.admin_snapshots_client.get_snapshot(self.snapshot['id'])
- self.assertEqual(200, resp_get.status)
self.assertEqual(status, snapshot_get['status'])
@test.attr(type='gate')
@@ -104,12 +100,10 @@
progress = '80%'
status = 'error'
progress_alias = self._get_progress_alias()
- resp, body = self.client.update_snapshot_status(self.snapshot['id'],
- status, progress)
- self.assertEqual(202, resp.status)
- resp_get, snapshot_get \
+ _, body = self.client.update_snapshot_status(self.snapshot['id'],
+ status, progress)
+ _, snapshot_get \
= self.admin_snapshots_client.get_snapshot(self.snapshot['id'])
- self.assertEqual(200, resp_get.status)
self.assertEqual(status, snapshot_get['status'])
self.assertEqual(progress, snapshot_get[progress_alias])
diff --git a/tempest/api/volume/admin/test_volume_hosts.py b/tempest/api/volume/admin/test_volume_hosts.py
index 01ba915..017363d 100644
--- a/tempest/api/volume/admin/test_volume_hosts.py
+++ b/tempest/api/volume/admin/test_volume_hosts.py
@@ -22,8 +22,7 @@
@test.attr(type='gate')
def test_list_hosts(self):
- resp, hosts = self.hosts_client.list_hosts()
- self.assertEqual(200, resp.status)
+ _, hosts = self.hosts_client.list_hosts()
self.assertTrue(len(hosts) >= 2, "No. of hosts are < 2,"
"response of list hosts is: % s" % hosts)
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index ecd8836..fa3b667 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -34,30 +34,28 @@
@test.attr(type='gate')
def test_list_quotas(self):
- resp, quotas = self.quotas_client.get_quota_set(self.demo_tenant_id)
- self.assertEqual(200, resp.status)
+ _, quotas = self.quotas_client.get_quota_set(self.demo_tenant_id)
for key in QUOTA_KEYS:
self.assertIn(key, quotas)
@test.attr(type='gate')
def test_list_default_quotas(self):
- resp, quotas = self.quotas_client.get_default_quota_set(
+ _, quotas = self.quotas_client.get_default_quota_set(
self.demo_tenant_id)
- self.assertEqual(200, resp.status)
for key in QUOTA_KEYS:
self.assertIn(key, quotas)
@test.attr(type='gate')
def test_update_all_quota_resources_for_tenant(self):
# Admin can update all the resource quota limits for a tenant
- resp, default_quota_set = self.quotas_client.get_default_quota_set(
+ _, default_quota_set = self.quotas_client.get_default_quota_set(
self.demo_tenant_id)
new_quota_set = {'gigabytes': 1009,
'volumes': 11,
'snapshots': 11}
# Update limits for all quota resources
- resp, quota_set = self.quotas_client.update_quota_set(
+ _, quota_set = self.quotas_client.update_quota_set(
self.demo_tenant_id,
**new_quota_set)
@@ -66,7 +64,6 @@
if k in QUOTA_KEYS)
self.addCleanup(self.quotas_client.update_quota_set,
self.demo_tenant_id, **cleanup_quota_set)
- self.assertEqual(200, resp.status)
# test that the specific values we set are actually in
# the final result. There is nothing here that ensures there
# would be no other values in there.
@@ -74,8 +71,7 @@
@test.attr(type='gate')
def test_show_quota_usage(self):
- resp, quota_usage = self.quotas_client.get_quota_usage(self.adm_tenant)
- self.assertEqual(200, resp.status)
+ _, quota_usage = self.quotas_client.get_quota_usage(self.adm_tenant)
for key in QUOTA_KEYS:
self.assertIn(key, quota_usage)
for usage_key in QUOTA_USAGE_KEYS:
@@ -83,17 +79,16 @@
@test.attr(type='gate')
def test_quota_usage(self):
- resp, quota_usage = self.quotas_client.get_quota_usage(
+ _, quota_usage = self.quotas_client.get_quota_usage(
self.demo_tenant_id)
volume = self.create_volume(size=1)
self.addCleanup(self.admin_volume_client.delete_volume,
volume['id'])
- resp, new_quota_usage = self.quotas_client.get_quota_usage(
+ _, new_quota_usage = self.quotas_client.get_quota_usage(
self.demo_tenant_id)
- self.assertEqual(200, resp.status)
self.assertEqual(quota_usage['volumes']['in_use'] + 1,
new_quota_usage['volumes']['in_use'])
@@ -115,9 +110,7 @@
self.quotas_client.update_quota_set(tenant_id,
volumes=(int(volume_default) + 5))
- resp, _ = self.quotas_client.delete_quota_set(tenant_id)
- self.assertEqual(200, resp.status)
-
+ self.quotas_client.delete_quota_set(tenant_id)
_, quota_set_new = self.quotas_client.get_quota_set(tenant_id)
self.assertEqual(volume_default, quota_set_new['volumes'])
diff --git a/tempest/api/volume/admin/test_volume_quotas_negative.py b/tempest/api/volume/admin/test_volume_quotas_negative.py
index ab88b90..515024f 100644
--- a/tempest/api/volume/admin/test_volume_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_quotas_negative.py
@@ -32,7 +32,7 @@
# NOTE(gfidente): no need to restore original quota set
# after the tests as they only work with tenant isolation.
- resp, quota_set = cls.quotas_client.update_quota_set(
+ _, quota_set = cls.quotas_client.update_quota_set(
cls.demo_tenant_id,
**cls.shared_quota_set)
@@ -63,7 +63,7 @@
**self.shared_quota_set)
new_quota_set = {'gigabytes': 2, 'volumes': 2, 'snapshots': 1}
- resp, quota_set = self.quotas_client.update_quota_set(
+ _, quota_set = self.quotas_client.update_quota_set(
self.demo_tenant_id,
**new_quota_set)
self.assertRaises(exceptions.OverLimit,
@@ -71,7 +71,7 @@
size=1)
new_quota_set = {'gigabytes': 2, 'volumes': 1, 'snapshots': 2}
- resp, quota_set = self.quotas_client.update_quota_set(
+ _, quota_set = self.quotas_client.update_quota_set(
self.demo_tenant_id,
**self.shared_quota_set)
self.assertRaises(exceptions.OverLimit,
diff --git a/tempest/api/volume/admin/test_volume_services.py b/tempest/api/volume/admin/test_volume_services.py
index 012c231..4a68e05 100644
--- a/tempest/api/volume/admin/test_volume_services.py
+++ b/tempest/api/volume/admin/test_volume_services.py
@@ -28,21 +28,19 @@
def setUpClass(cls):
super(VolumesServicesTestJSON, cls).setUpClass()
cls.client = cls.os_adm.volume_services_client
- resp, cls.services = cls.client.list_services()
+ _, cls.services = cls.client.list_services()
cls.host_name = cls.services[0]['host']
cls.binary_name = cls.services[0]['binary']
@test.attr(type='gate')
def test_list_services(self):
- resp, services = self.client.list_services()
- self.assertEqual(200, resp.status)
+ _, services = self.client.list_services()
self.assertNotEqual(0, len(services))
@test.attr(type='gate')
def test_get_service_by_service_binary_name(self):
params = {'binary': self.binary_name}
- resp, services = self.client.list_services(params)
- self.assertEqual(200, resp.status)
+ _, services = self.client.list_services(params)
self.assertNotEqual(0, len(services))
for service in services:
self.assertEqual(self.binary_name, service['binary'])
@@ -53,7 +51,7 @@
service['host'] == self.host_name]
params = {'host': self.host_name}
- resp, services = self.client.list_services(params)
+ _, services = self.client.list_services(params)
# we could have a periodic job checkin between the 2 service
# lookups, so only compare binary lists.
@@ -67,8 +65,7 @@
def test_get_service_by_service_and_host_name(self):
params = {'host': self.host_name, 'binary': self.binary_name}
- resp, services = self.client.list_services(params)
- self.assertEqual(200, resp.status)
+ _, services = self.client.list_services(params)
self.assertEqual(1, len(services))
self.assertEqual(self.host_name, services[0]['host'])
self.assertEqual(self.binary_name, services[0]['binary'])
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index 3b8c214..070d38f 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -25,19 +25,16 @@
_interface = "json"
def _delete_volume(self, volume_id):
- resp, _ = self.volumes_client.delete_volume(volume_id)
- self.assertEqual(202, resp.status)
+ self.volumes_client.delete_volume(volume_id)
self.volumes_client.wait_for_resource_deletion(volume_id)
def _delete_volume_type(self, volume_type_id):
- resp, _ = self.client.delete_volume_type(volume_type_id)
- self.assertEqual(202, resp.status)
+ self.client.delete_volume_type(volume_type_id)
@test.attr(type='smoke')
def test_volume_type_list(self):
# List Volume types.
- resp, body = self.client.list_volume_types()
- self.assertEqual(200, resp.status)
+ _, body = self.client.list_volume_types()
self.assertIsInstance(body, list)
@test.attr(type='smoke')
@@ -51,17 +48,15 @@
extra_specs = {"storage_protocol": proto,
"vendor_name": vendor}
body = {}
- resp, body = self.client.create_volume_type(
+ _, body = self.client.create_volume_type(
vol_type_name,
extra_specs=extra_specs)
- self.assertEqual(200, resp.status)
self.assertIn('id', body)
self.addCleanup(self._delete_volume_type, body['id'])
self.assertIn('name', body)
- resp, volume = self.volumes_client.create_volume(
+ _, volume = self.volumes_client.create_volume(
size=1, display_name=vol_name,
volume_type=vol_type_name)
- self.assertEqual(200, resp.status)
self.assertIn('id', volume)
self.addCleanup(self._delete_volume, volume['id'])
self.assertIn('display_name', volume)
@@ -72,8 +67,7 @@
"Field volume id is empty or not found.")
self.volumes_client.wait_for_volume_status(volume['id'],
'available')
- resp, fetched_volume = self.volumes_client.get_volume(volume['id'])
- self.assertEqual(200, resp.status)
+ _, fetched_volume = self.volumes_client.get_volume(volume['id'])
self.assertEqual(vol_name, fetched_volume['display_name'],
'The fetched Volume is different '
'from the created Volume')
@@ -93,10 +87,9 @@
vendor = CONF.volume.vendor_name
extra_specs = {"storage_protocol": proto,
"vendor_name": vendor}
- resp, body = self.client.create_volume_type(
+ _, body = self.client.create_volume_type(
name,
extra_specs=extra_specs)
- self.assertEqual(200, resp.status)
self.assertIn('id', body)
self.addCleanup(self._delete_volume_type, body['id'])
self.assertIn('name', body)
@@ -105,8 +98,7 @@
"to the requested name")
self.assertTrue(body['id'] is not None,
"Field volume_type id is empty or not found.")
- resp, fetched_volume_type = self.client.get_volume_type(body['id'])
- self.assertEqual(200, resp.status)
+ _, fetched_volume_type = self.client.get_volume_type(body['id'])
self.assertEqual(name, fetched_volume_type['name'],
'The fetched Volume_type is different '
'from the created Volume_type')
@@ -123,15 +115,13 @@
provider = "LuksEncryptor"
control_location = "front-end"
name = data_utils.rand_name("volume-type-")
- resp, body = self.client.create_volume_type(name)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_volume_type(name)
self.addCleanup(self._delete_volume_type, body['id'])
# Create encryption type
- resp, encryption_type = self.client.create_encryption_type(
+ _, encryption_type = self.client.create_encryption_type(
body['id'], provider=provider,
control_location=control_location)
- self.assertEqual(200, resp.status)
self.assertIn('volume_type_id', encryption_type)
self.assertEqual(provider, encryption_type['provider'],
"The created encryption_type provider is not equal "
@@ -141,9 +131,8 @@
"equal to the requested control_location")
# Get encryption type
- resp, fetched_encryption_type = self.client.get_encryption_type(
+ _, fetched_encryption_type = self.client.get_encryption_type(
encryption_type['volume_type_id'])
- self.assertEqual(200, resp.status)
self.assertEqual(provider,
fetched_encryption_type['provider'],
'The fetched encryption_type provider is different '
@@ -154,13 +143,11 @@
'different from the created encryption_type')
# Delete encryption type
- resp, _ = self.client.delete_encryption_type(
+ self.client.delete_encryption_type(
encryption_type['volume_type_id'])
- self.assertEqual(202, resp.status)
resource = {"id": encryption_type['volume_type_id'],
"type": "encryption-type"}
self.client.wait_for_resource_deletion(resource)
- resp, deleted_encryption_type = self.client.get_encryption_type(
+ _, deleted_encryption_type = self.client.get_encryption_type(
encryption_type['volume_type_id'])
- self.assertEqual(200, resp.status)
self.assertEmpty(deleted_encryption_type)
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs.py b/tempest/api/volume/admin/test_volume_types_extra_specs.py
index 06a0b34..c682866 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs.py
@@ -25,7 +25,7 @@
def setUpClass(cls):
super(VolumeTypesExtraSpecsTest, cls).setUpClass()
vol_type_name = data_utils.rand_name('Volume-type-')
- resp, cls.volume_type = cls.client.create_volume_type(vol_type_name)
+ _, cls.volume_type = cls.client.create_volume_type(vol_type_name)
@classmethod
def tearDownClass(cls):
@@ -36,14 +36,12 @@
def test_volume_type_extra_specs_list(self):
# List Volume types extra specs.
extra_specs = {"spec1": "val1"}
- resp, body = self.client.create_volume_type_extra_specs(
+ _, body = self.client.create_volume_type_extra_specs(
self.volume_type['id'], extra_specs)
- self.assertEqual(200, resp.status)
self.assertEqual(extra_specs, body,
"Volume type extra spec incorrectly created")
- resp, body = self.client.list_volume_types_extra_specs(
+ _, body = self.client.list_volume_types_extra_specs(
self.volume_type['id'])
- self.assertEqual(200, resp.status)
self.assertIsInstance(body, dict)
self.assertIn('spec1', body)
@@ -51,18 +49,16 @@
def test_volume_type_extra_specs_update(self):
# Update volume type extra specs
extra_specs = {"spec2": "val1"}
- resp, body = self.client.create_volume_type_extra_specs(
+ _, body = self.client.create_volume_type_extra_specs(
self.volume_type['id'], extra_specs)
- self.assertEqual(200, resp.status)
self.assertEqual(extra_specs, body,
"Volume type extra spec incorrectly created")
extra_spec = {"spec2": "val2"}
- resp, body = self.client.update_volume_type_extra_specs(
+ _, body = self.client.update_volume_type_extra_specs(
self.volume_type['id'],
extra_spec.keys()[0],
extra_spec)
- self.assertEqual(200, resp.status)
self.assertIn('spec2', body)
self.assertEqual(extra_spec['spec2'], body['spec2'],
"Volume type extra spec incorrectly updated")
@@ -71,21 +67,18 @@
def test_volume_type_extra_spec_create_get_delete(self):
# Create/Get/Delete volume type extra spec.
extra_specs = {"spec3": "val1"}
- resp, body = self.client.create_volume_type_extra_specs(
+ _, body = self.client.create_volume_type_extra_specs(
self.volume_type['id'],
extra_specs)
- self.assertEqual(200, resp.status)
self.assertEqual(extra_specs, body,
"Volume type extra spec incorrectly created")
- resp, _ = self.client.get_volume_type_extra_specs(
+ self.client.get_volume_type_extra_specs(
self.volume_type['id'],
extra_specs.keys()[0])
- self.assertEqual(200, resp.status)
self.assertEqual(extra_specs, body,
"Volume type extra spec incorrectly fetched")
- resp, _ = self.client.delete_volume_type_extra_specs(
+ self.client.delete_volume_type_extra_specs(
self.volume_type['id'],
extra_specs.keys()[0])
- self.assertEqual(202, resp.status)
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index da421dc..ff4f113 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -29,7 +29,7 @@
super(ExtraSpecsNegativeTest, cls).setUpClass()
vol_type_name = data_utils.rand_name('Volume-type-')
cls.extra_specs = {"spec1": "val1"}
- resp, cls.volume_type = cls.client.create_volume_type(
+ _, cls.volume_type = cls.client.create_volume_type(
vol_type_name,
extra_specs=cls.extra_specs)
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index 008f739..d6db1df 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -33,8 +33,8 @@
# Create a test shared volume for tests
vol_name = utils.rand_name(cls.__name__ + '-Volume-')
- resp, cls.volume = cls.client.create_volume(size=1,
- display_name=vol_name)
+ _, cls.volume = cls.client.create_volume(size=1,
+ display_name=vol_name)
cls.client.wait_for_volume_status(cls.volume['id'], 'available')
@classmethod
@@ -47,9 +47,9 @@
def _reset_volume_status(self, volume_id, status):
# Reset the volume status
- resp, body = self.admin_volume_client.reset_volume_status(volume_id,
- status)
- return resp, body
+ _, body = self.admin_volume_client.reset_volume_status(volume_id,
+ status)
+ return _, body
def tearDown(self):
# Set volume's status to available after test
@@ -59,8 +59,8 @@
def _create_temp_volume(self):
# Create a temp volume for force delete tests
vol_name = utils.rand_name('Volume')
- resp, temp_volume = self.client.create_volume(size=1,
- display_name=vol_name)
+ _, temp_volume = self.client.create_volume(size=1,
+ display_name=vol_name)
self.client.wait_for_volume_status(temp_volume['id'], 'available')
return temp_volume
@@ -69,19 +69,16 @@
# Create volume, reset volume status, and force delete temp volume
temp_volume = self._create_temp_volume()
if status:
- resp, body = self._reset_volume_status(temp_volume['id'], status)
- self.assertEqual(202, resp.status)
- resp_delete, volume_delete = self.admin_volume_client.\
+ _, body = self._reset_volume_status(temp_volume['id'], status)
+ _, volume_delete = self.admin_volume_client.\
force_delete_volume(temp_volume['id'])
- self.assertEqual(202, resp_delete.status)
self.client.wait_for_resource_deletion(temp_volume['id'])
@test.attr(type='gate')
def test_volume_reset_status(self):
# test volume reset status : available->error->available
- resp, body = self._reset_volume_status(self.volume['id'], 'error')
- self.assertEqual(202, resp.status)
- resp_get, volume_get = self.admin_volume_client.get_volume(
+ _, body = self._reset_volume_status(self.volume['id'], 'error')
+ _, volume_get = self.admin_volume_client.get_volume(
self.volume['id'])
self.assertEqual('error', volume_get['status'])
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index f9fbe18..3699e9c 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -43,9 +43,8 @@
# Create backup
backup_name = data_utils.rand_name('Backup')
create_backup = self.backups_adm_client.create_backup
- resp, backup = create_backup(self.volume['id'],
- name=backup_name)
- self.assertEqual(202, resp.status)
+ _, backup = create_backup(self.volume['id'],
+ name=backup_name)
self.addCleanup(self.backups_adm_client.delete_backup,
backup['id'])
self.assertEqual(backup_name, backup['name'])
@@ -55,19 +54,16 @@
'available')
# Get a given backup
- resp, backup = self.backups_adm_client.get_backup(backup['id'])
- self.assertEqual(200, resp.status)
+ _, backup = self.backups_adm_client.get_backup(backup['id'])
self.assertEqual(backup_name, backup['name'])
# Get all backups with detail
- resp, backups = self.backups_adm_client.list_backups_with_detail()
- self.assertEqual(200, resp.status)
+ _, backups = self.backups_adm_client.list_backups_with_detail()
self.assertIn((backup['name'], backup['id']),
[(m['name'], m['id']) for m in backups])
# Restore backup
- resp, restore = self.backups_adm_client.restore_backup(backup['id'])
- self.assertEqual(202, resp.status)
+ _, restore = self.backups_adm_client.restore_backup(backup['id'])
# Delete backup
self.addCleanup(self.volumes_adm_client.delete_volume,
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index b7de767..3cd0827 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -63,8 +63,7 @@
cls.os.volume_availability_zone_client)
# Special fields and resp code for cinder v1
cls.special_fields = {'name_field': 'display_name',
- 'descrip_field': 'display_description',
- 'create_resp': 200}
+ 'descrip_field': 'display_description'}
elif cls._api_version == 2:
if not CONF.volume_feature_enabled.api_v2:
@@ -76,8 +75,7 @@
cls.os.volume_v2_availability_zone_client)
# Special fields and resp code for cinder v2
cls.special_fields = {'name_field': 'name',
- 'descrip_field': 'description',
- 'create_resp': 202}
+ 'descrip_field': 'description'}
else:
msg = ("Invalid Cinder API version (%s)" % cls._api_version)
@@ -96,11 +94,9 @@
name = data_utils.rand_name('Volume')
name_field = cls.special_fields['name_field']
- expect_status = cls.special_fields['create_resp']
kwargs[name_field] = name
- resp, volume = cls.volumes_client.create_volume(size, **kwargs)
- assert expect_status == resp.status
+ _, volume = cls.volumes_client.create_volume(size, **kwargs)
cls.volumes.append(volume)
cls.volumes_client.wait_for_volume_status(volume['id'], 'available')
@@ -109,9 +105,8 @@
@classmethod
def create_snapshot(cls, volume_id=1, **kwargs):
"""Wrapper utility that returns a test snapshot."""
- resp, snapshot = cls.snapshots_client.create_snapshot(volume_id,
- **kwargs)
- assert 200 == resp.status
+ _, snapshot = cls.snapshots_client.create_snapshot(volume_id,
+ **kwargs)
cls.snapshots.append(snapshot)
cls.snapshots_client.wait_for_snapshot_status(snapshot['id'],
'available')
diff --git a/tempest/api/volume/test_availability_zone.py b/tempest/api/volume/test_availability_zone.py
index 25b7b85..c026f71 100644
--- a/tempest/api/volume/test_availability_zone.py
+++ b/tempest/api/volume/test_availability_zone.py
@@ -31,8 +31,7 @@
@test.attr(type='gate')
def test_get_availability_zone_list(self):
# List of availability zone
- resp, availability_zone = self.client.get_availability_zone_list()
- self.assertEqual(200, resp.status)
+ _, availability_zone = self.client.get_availability_zone_list()
self.assertTrue(len(availability_zone) > 0)
diff --git a/tempest/api/volume/test_extensions.py b/tempest/api/volume/test_extensions.py
index ff00dd1..4fc6ee4 100644
--- a/tempest/api/volume/test_extensions.py
+++ b/tempest/api/volume/test_extensions.py
@@ -30,8 +30,7 @@
@test.attr(type='gate')
def test_list_extensions(self):
# List of all extensions
- resp, extensions = self.volumes_extension_client.list_extensions()
- self.assertEqual(200, resp.status)
+ _, extensions = self.volumes_extension_client.list_extensions()
if len(CONF.volume_feature_enabled.api_extensions) == 0:
raise self.skipException('There are not any extensions configured')
extension_list = [extension.get('alias') for extension in extensions]
diff --git a/tempest/api/volume/test_snapshot_metadata.py b/tempest/api/volume/test_snapshot_metadata.py
index d2c4ab7..94ba095 100644
--- a/tempest/api/volume/test_snapshot_metadata.py
+++ b/tempest/api/volume/test_snapshot_metadata.py
@@ -44,19 +44,15 @@
"key3": "value3"}
expected = {"key2": "value2",
"key3": "value3"}
- resp, body = self.client.create_snapshot_metadata(self.snapshot_id,
- metadata)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_snapshot_metadata(self.snapshot_id,
+ metadata)
# Get the metadata of the snapshot
- resp, body = self.client.get_snapshot_metadata(self.snapshot_id)
- self.assertEqual(200, resp.status)
+ _, body = self.client.get_snapshot_metadata(self.snapshot_id)
self.assertEqual(metadata, body)
# Delete one item metadata of the snapshot
- resp, body = self.client.delete_snapshot_metadata_item(
- self.snapshot_id,
- "key1")
- self.assertEqual(200, resp.status)
- resp, body = self.client.get_snapshot_metadata(self.snapshot_id)
+ self.client.delete_snapshot_metadata_item(
+ self.snapshot_id, "key1")
+ _, body = self.client.get_snapshot_metadata(self.snapshot_id)
self.assertEqual(expected, body)
@test.attr(type='gate')
@@ -68,21 +64,16 @@
update = {"key3": "value3_update",
"key4": "value4"}
# Create metadata for the snapshot
- resp, body = self.client.create_snapshot_metadata(self.snapshot_id,
- metadata)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_snapshot_metadata(self.snapshot_id,
+ metadata)
# Get the metadata of the snapshot
- resp, body = self.client.get_snapshot_metadata(self.snapshot_id)
- self.assertEqual(200, resp.status)
+ _, body = self.client.get_snapshot_metadata(self.snapshot_id)
self.assertEqual(metadata, body)
# Update metadata item
- resp, body = self.client.update_snapshot_metadata(
- self.snapshot_id,
- update)
- self.assertEqual(200, resp.status)
+ _, body = self.client.update_snapshot_metadata(
+ self.snapshot_id, update)
# Get the metadata of the snapshot
- resp, body = self.client.get_snapshot_metadata(self.snapshot_id)
- self.assertEqual(200, resp.status)
+ _, body = self.client.get_snapshot_metadata(self.snapshot_id)
self.assertEqual(update, body)
@test.attr(type='gate')
@@ -96,21 +87,16 @@
"key2": "value2",
"key3": "value3_update"}
# Create metadata for the snapshot
- resp, body = self.client.create_snapshot_metadata(self.snapshot_id,
- metadata)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_snapshot_metadata(self.snapshot_id,
+ metadata)
# Get the metadata of the snapshot
- resp, body = self.client.get_snapshot_metadata(self.snapshot_id)
+ _, body = self.client.get_snapshot_metadata(self.snapshot_id)
self.assertEqual(metadata, body)
# Update metadata item
- resp, body = self.client.update_snapshot_metadata_item(
- self.snapshot_id,
- "key3",
- update_item)
- self.assertEqual(200, resp.status)
+ _, body = self.client.update_snapshot_metadata_item(
+ self.snapshot_id, "key3", update_item)
# Get the metadata of the snapshot
- resp, body = self.client.get_snapshot_metadata(self.snapshot_id)
- self.assertEqual(200, resp.status)
+ _, body = self.client.get_snapshot_metadata(self.snapshot_id)
self.assertEqual(expect, body)
diff --git a/tempest/api/volume/test_volume_metadata.py b/tempest/api/volume/test_volume_metadata.py
index 0505f19..ac760aa 100644
--- a/tempest/api/volume/test_volume_metadata.py
+++ b/tempest/api/volume/test_volume_metadata.py
@@ -42,19 +42,15 @@
"key3": "value3",
"key4": "<value&special_chars>"}
- rsp, body = self.volumes_client.create_volume_metadata(self.volume_id,
- metadata)
- self.assertEqual(200, rsp.status)
+ _, body = self.volumes_client.create_volume_metadata(self.volume_id,
+ metadata)
# Get the metadata of the volume
- resp, body = self.volumes_client.get_volume_metadata(self.volume_id)
- self.assertEqual(200, resp.status)
+ _, body = self.volumes_client.get_volume_metadata(self.volume_id)
self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
# Delete one item metadata of the volume
- rsp, body = self.volumes_client.delete_volume_metadata_item(
- self.volume_id,
- "key1")
- self.assertEqual(200, rsp.status)
- resp, body = self.volumes_client.get_volume_metadata(self.volume_id)
+ self.volumes_client.delete_volume_metadata_item(
+ self.volume_id, "key1")
+ _, body = self.volumes_client.get_volume_metadata(self.volume_id)
self.assertNotIn("key1", body)
del metadata["key1"]
self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
@@ -70,22 +66,16 @@
"key1": "value1_update"}
# Create metadata for the volume
- resp, body = self.volumes_client.create_volume_metadata(
- self.volume_id,
- metadata)
- self.assertEqual(200, resp.status)
+ _, body = self.volumes_client.create_volume_metadata(
+ self.volume_id, metadata)
# Get the metadata of the volume
- resp, body = self.volumes_client.get_volume_metadata(self.volume_id)
- self.assertEqual(200, resp.status)
+ _, body = self.volumes_client.get_volume_metadata(self.volume_id)
self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
# Update metadata
- resp, body = self.volumes_client.update_volume_metadata(
- self.volume_id,
- update)
- self.assertEqual(200, resp.status)
+ _, body = self.volumes_client.update_volume_metadata(
+ self.volume_id, update)
# Get the metadata of the volume
- resp, body = self.volumes_client.get_volume_metadata(self.volume_id)
- self.assertEqual(200, resp.status)
+ _, body = self.volumes_client.get_volume_metadata(self.volume_id)
self.assertThat(body.items(), matchers.ContainsAll(update.items()))
@test.attr(type='gate')
@@ -99,20 +89,14 @@
"key2": "value2",
"key3": "value3_update"}
# Create metadata for the volume
- resp, body = self.volumes_client.create_volume_metadata(
- self.volume_id,
- metadata)
- self.assertEqual(200, resp.status)
+ _, body = self.volumes_client.create_volume_metadata(
+ self.volume_id, metadata)
self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
# Update metadata item
- resp, body = self.volumes_client.update_volume_metadata_item(
- self.volume_id,
- "key3",
- update_item)
- self.assertEqual(200, resp.status)
+ _, body = self.volumes_client.update_volume_metadata_item(
+ self.volume_id, "key3", update_item)
# Get the metadata of the volume
- resp, body = self.volumes_client.get_volume_metadata(self.volume_id)
- self.assertEqual(200, resp.status)
+ _, body = self.volumes_client.get_volume_metadata(self.volume_id)
self.assertThat(body.items(), matchers.ContainsAll(expect.items()))
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index bf61222..4a6ba03 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -47,8 +47,7 @@
def _delete_volume(self, volume_id):
# Delete the specified volume using admin creds
- resp, _ = self.adm_client.delete_volume(volume_id)
- self.assertEqual(202, resp.status)
+ self.adm_client.delete_volume(volume_id)
self.adm_client.wait_for_resource_deletion(volume_id)
@test.attr(type='gate')
@@ -58,28 +57,24 @@
self.addCleanup(self._delete_volume, volume['id'])
# Create a volume transfer
- resp, transfer = self.client.create_volume_transfer(volume['id'])
- self.assertEqual(202, resp.status)
+ _, transfer = self.client.create_volume_transfer(volume['id'])
transfer_id = transfer['id']
auth_key = transfer['auth_key']
self.client.wait_for_volume_status(volume['id'],
'awaiting-transfer')
# Get a volume transfer
- resp, body = self.client.get_volume_transfer(transfer_id)
- self.assertEqual(200, resp.status)
+ _, body = self.client.get_volume_transfer(transfer_id)
self.assertEqual(volume['id'], body['volume_id'])
# List volume transfers, the result should be greater than
# or equal to 1
- resp, body = self.client.list_volume_transfers()
- self.assertEqual(200, resp.status)
+ _, body = self.client.list_volume_transfers()
self.assertThat(len(body), matchers.GreaterThan(0))
# Accept a volume transfer by alt_tenant
- resp, body = self.alt_client.accept_volume_transfer(transfer_id,
- auth_key)
- self.assertEqual(202, resp.status)
+ _, body = self.alt_client.accept_volume_transfer(transfer_id,
+ auth_key)
self.alt_client.wait_for_volume_status(volume['id'], 'available')
def test_create_list_delete_volume_transfer(self):
@@ -88,15 +83,13 @@
self.addCleanup(self._delete_volume, volume['id'])
# Create a volume transfer
- resp, body = self.client.create_volume_transfer(volume['id'])
- self.assertEqual(202, resp.status)
+ _, body = self.client.create_volume_transfer(volume['id'])
transfer_id = body['id']
self.client.wait_for_volume_status(volume['id'],
'awaiting-transfer')
# List all volume transfers (looking for the one we created)
- resp, body = self.client.list_volume_transfers()
- self.assertEqual(200, resp.status)
+ _, body = self.client.list_volume_transfers()
for transfer in body:
if volume['id'] == transfer['volume_id']:
break
@@ -104,8 +97,7 @@
self.fail('Transfer not found for volume %s' % volume['id'])
# Delete a volume transfer
- resp, body = self.client.delete_volume_transfer(transfer_id)
- self.assertEqual(202, resp.status)
+ self.client.delete_volume_transfer(transfer_id)
self.client.wait_for_volume_status(volume['id'], 'available')
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 6fef564..c87878d 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -40,6 +40,10 @@
# Create a test shared volume for attach/detach tests
cls.volume = cls.create_volume()
+ def _delete_image_with_wait(self, image_id):
+ self.image_client.delete_image(image_id)
+ self.image_client.wait_for_resource_deletion(image_id)
+
@classmethod
def tearDownClass(cls):
# Delete the test instance
@@ -54,13 +58,11 @@
def test_attach_detach_volume_to_instance(self):
# Volume is attached and detached successfully from an instance
mountpoint = '/dev/vdc'
- resp, body = self.client.attach_volume(self.volume['id'],
- self.server['id'],
- mountpoint)
- self.assertEqual(202, resp.status)
+ _, body = self.client.attach_volume(self.volume['id'],
+ self.server['id'],
+ mountpoint)
self.client.wait_for_volume_status(self.volume['id'], 'in-use')
- resp, body = self.client.detach_volume(self.volume['id'])
- self.assertEqual(202, resp.status)
+ _, body = self.client.detach_volume(self.volume['id'])
self.client.wait_for_volume_status(self.volume['id'], 'available')
@test.stresstest(class_setup_per='process')
@@ -69,10 +71,9 @@
def test_get_volume_attachment(self):
# Verify that a volume's attachment information is retrieved
mountpoint = '/dev/vdc'
- resp, body = self.client.attach_volume(self.volume['id'],
- self.server['id'],
- mountpoint)
- self.assertEqual(202, resp.status)
+ _, body = self.client.attach_volume(self.volume['id'],
+ self.server['id'],
+ mountpoint)
self.client.wait_for_volume_status(self.volume['id'], 'in-use')
# NOTE(gfidente): added in reverse order because functions will be
# called in reverse order to the order they are added (LIFO)
@@ -80,8 +81,7 @@
self.volume['id'],
'available')
self.addCleanup(self.client.detach_volume, self.volume['id'])
- resp, volume = self.client.get_volume(self.volume['id'])
- self.assertEqual(200, resp.status)
+ _, volume = self.client.get_volume(self.volume['id'])
self.assertIn('attachments', volume)
attachment = self.client.get_attachment_from_volume(volume)
self.assertEqual(mountpoint, attachment['device'])
@@ -97,41 +97,25 @@
# there is no way to delete it from Cinder, so we delete it from Glance
# using the Glance image_client and from Cinder via tearDownClass.
image_name = data_utils.rand_name('Image-')
- resp, body = self.client.upload_volume(self.volume['id'],
- image_name,
- CONF.volume.disk_format)
+ _, body = self.client.upload_volume(self.volume['id'],
+ image_name,
+ CONF.volume.disk_format)
image_id = body["image_id"]
self.addCleanup(self.image_client.delete_image, image_id)
- self.assertEqual(202, resp.status)
self.image_client.wait_for_image_status(image_id, 'active')
self.client.wait_for_volume_status(self.volume['id'], 'available')
@test.attr(type='gate')
- def test_volume_extend(self):
- # Extend Volume Test.
- extend_size = int(self.volume['size']) + 1
- resp, body = self.client.extend_volume(self.volume['id'], extend_size)
- self.assertEqual(202, resp.status)
- self.client.wait_for_volume_status(self.volume['id'], 'available')
- resp, volume = self.client.get_volume(self.volume['id'])
- self.assertEqual(200, resp.status)
- self.assertEqual(int(volume['size']), extend_size)
-
- @test.attr(type='gate')
def test_reserve_unreserve_volume(self):
# Mark volume as reserved.
- resp, body = self.client.reserve_volume(self.volume['id'])
- self.assertEqual(202, resp.status)
+ _, body = self.client.reserve_volume(self.volume['id'])
# To get the volume info
- resp, body = self.client.get_volume(self.volume['id'])
- self.assertEqual(200, resp.status)
+ _, body = self.client.get_volume(self.volume['id'])
self.assertIn('attaching', body['status'])
# Unmark volume as reserved.
- resp, body = self.client.unreserve_volume(self.volume['id'])
- self.assertEqual(202, resp.status)
+ _, body = self.client.unreserve_volume(self.volume['id'])
# To get the volume info
- resp, body = self.client.get_volume(self.volume['id'])
- self.assertEqual(200, resp.status)
+ _, body = self.client.get_volume(self.volume['id'])
self.assertIn('available', body['status'])
def _is_true(self, val):
@@ -141,26 +125,21 @@
def test_volume_readonly_update(self):
# Update volume readonly true
readonly = True
- resp, body = self.client.update_volume_readonly(self.volume['id'],
- readonly)
- self.assertEqual(202, resp.status)
-
+ _, body = self.client.update_volume_readonly(self.volume['id'],
+ readonly)
# Get Volume information
- resp, fetched_volume = self.client.get_volume(self.volume['id'])
+ _, fetched_volume = self.client.get_volume(self.volume['id'])
bool_flag = self._is_true(fetched_volume['metadata']['readonly'])
- self.assertEqual(200, resp.status)
self.assertEqual(True, bool_flag)
# Update volume readonly false
readonly = False
- resp, body = self.client.update_volume_readonly(self.volume['id'],
- readonly)
- self.assertEqual(202, resp.status)
+ _, body = self.client.update_volume_readonly(self.volume['id'],
+ readonly)
# Get Volume information
- resp, fetched_volume = self.client.get_volume(self.volume['id'])
+ _, fetched_volume = self.client.get_volume(self.volume['id'])
bool_flag = self._is_true(fetched_volume['metadata']['readonly'])
- self.assertEqual(200, resp.status)
self.assertEqual(False, bool_flag)
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
new file mode 100644
index 0000000..c9e80aa
--- /dev/null
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -0,0 +1,51 @@
+# 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.
+
+from tempest.api.volume import base
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class VolumesV2ExtendTest(base.BaseVolumeTest):
+
+ @classmethod
+ @test.safe_setup
+ def setUpClass(cls):
+ super(VolumesV2ExtendTest, cls).setUpClass()
+ cls.client = cls.volumes_client
+
+ @test.attr(type='gate')
+ def test_volume_extend(self):
+ # Extend Volume Test.
+ self.volume = self.create_volume()
+ extend_size = int(self.volume['size']) + 1
+ _, body = self.client.extend_volume(self.volume['id'], extend_size)
+ self.client.wait_for_volume_status(self.volume['id'], 'available')
+ _, volume = self.client.get_volume(self.volume['id'])
+ self.assertEqual(int(volume['size']), extend_size)
+
+
+class VolumesV2ExtendTestXML(VolumesV2ExtendTest):
+ _interface = "xml"
+
+
+class VolumesV1ExtendTest(VolumesV2ExtendTest):
+ _api_version = 1
+
+
+class VolumesV1ExtendTestXML(VolumesV1ExtendTest):
+ _interface = "xml"
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 82208aa..a346a17 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -32,11 +32,9 @@
cls.name_field = cls.special_fields['name_field']
cls.descrip_field = cls.special_fields['descrip_field']
- cls.create_resp = cls.special_fields['create_resp']
def _delete_volume(self, volume_id):
- resp, _ = self.client.delete_volume(volume_id)
- self.assertEqual(202, resp.status)
+ self.client.delete_volume(volume_id)
self.client.wait_for_resource_deletion(volume_id)
def _is_true(self, val):
@@ -56,8 +54,7 @@
# Create a volume
kwargs[self.name_field] = v_name
kwargs['metadata'] = metadata
- resp, volume = self.client.create_volume(**kwargs)
- self.assertEqual(self.create_resp, resp.status)
+ _, volume = self.client.create_volume(**kwargs)
self.assertIn('id', volume)
self.addCleanup(self._delete_volume, volume['id'])
self.client.wait_for_volume_status(volume['id'], 'available')
@@ -68,8 +65,7 @@
self.assertTrue(volume['id'] is not None,
"Field volume id is empty or not found.")
# Get Volume information
- resp, fetched_volume = self.client.get_volume(volume['id'])
- self.assertEqual(200, resp.status)
+ _, fetched_volume = self.client.get_volume(volume['id'])
self.assertEqual(v_name,
fetched_volume[self.name_field],
'The fetched Volume name is different '
@@ -94,21 +90,18 @@
# Update Volume
# Test volume update when display_name is same with original value
params = {self.name_field: v_name}
- resp, update_volume = self.client.update_volume(volume['id'], **params)
- self.assertEqual(200, resp.status)
+ _, update_volume = self.client.update_volume(volume['id'], **params)
# Test volume update when display_name is new
new_v_name = data_utils.rand_name('new-Volume')
new_desc = 'This is the new description of volume'
params = {self.name_field: new_v_name,
self.descrip_field: new_desc}
- resp, update_volume = self.client.update_volume(volume['id'], **params)
+ _, update_volume = self.client.update_volume(volume['id'], **params)
# Assert response body for update_volume method
- self.assertEqual(200, resp.status)
self.assertEqual(new_v_name, update_volume[self.name_field])
self.assertEqual(new_desc, update_volume[self.descrip_field])
# Assert response body for get_volume method
- resp, updated_volume = self.client.get_volume(volume['id'])
- self.assertEqual(200, resp.status)
+ _, updated_volume = self.client.get_volume(volume['id'])
self.assertEqual(volume['id'], updated_volume['id'])
self.assertEqual(new_v_name, updated_volume[self.name_field])
self.assertEqual(new_desc, updated_volume[self.descrip_field])
@@ -123,17 +116,15 @@
new_v_desc = data_utils.rand_name('@#$%^* description')
params = {self.descrip_field: new_v_desc,
'availability_zone': volume['availability_zone']}
- resp, new_volume = self.client.create_volume(size=1, **params)
- self.assertEqual(self.create_resp, resp.status)
+ _, new_volume = self.client.create_volume(size=1, **params)
self.assertIn('id', new_volume)
self.addCleanup(self._delete_volume, new_volume['id'])
self.client.wait_for_volume_status(new_volume['id'], 'available')
params = {self.name_field: volume[self.name_field],
self.descrip_field: volume[self.descrip_field]}
- resp, update_volume = self.client.update_volume(new_volume['id'],
- **params)
- self.assertEqual(200, resp.status)
+ _, update_volume = self.client.update_volume(new_volume['id'],
+ **params)
# NOTE(jdg): Revert back to strict true/false checking
# after fix for bug #1227837 merges
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index ff225a2..272a41a 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -67,7 +67,7 @@
cls.metadata = {'Type': 'work'}
for i in range(3):
volume = cls.create_volume(metadata=cls.metadata)
- resp, volume = cls.client.get_volume(volume['id'])
+ _, volume = cls.client.get_volume(volume['id'])
cls.volume_list.append(volume)
cls.volume_id_list.append(volume['id'])
@@ -75,7 +75,7 @@
def tearDownClass(cls):
# Delete the created volumes
for volid in cls.volume_id_list:
- resp, _ = cls.client.delete_volume(volid)
+ cls.client.delete_volume(volid)
cls.client.wait_for_resource_deletion(volid)
super(VolumesV2ListTestJSON, cls).tearDownClass()
@@ -85,12 +85,11 @@
and validates result.
"""
if with_detail:
- resp, fetched_vol_list = \
+ _, fetched_vol_list = \
self.client.list_volumes_with_detail(params=params)
else:
- resp, fetched_vol_list = self.client.list_volumes(params=params)
+ _, fetched_vol_list = self.client.list_volumes(params=params)
- self.assertEqual(200, resp.status)
# Validating params of fetched volumes
# In v2, only list detail view includes items in params.
# In v1, list view and list detail view are same. So the
@@ -113,8 +112,7 @@
def test_volume_list(self):
# Get a list of Volumes
# Fetch all volumes
- resp, fetched_list = self.client.list_volumes()
- self.assertEqual(200, resp.status)
+ _, fetched_list = self.client.list_volumes()
self.assertVolumesIn(fetched_list, self.volume_list,
fields=self.VOLUME_FIELDS)
@@ -122,16 +120,14 @@
def test_volume_list_with_details(self):
# Get a list of Volumes with details
# Fetch all Volumes
- resp, fetched_list = self.client.list_volumes_with_detail()
- self.assertEqual(200, resp.status)
+ _, fetched_list = self.client.list_volumes_with_detail()
self.assertVolumesIn(fetched_list, self.volume_list)
@test.attr(type='gate')
def test_volume_list_by_name(self):
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
params = {self.name: volume[self.name]}
- resp, fetched_vol = self.client.list_volumes(params)
- self.assertEqual(200, resp.status)
+ _, fetched_vol = self.client.list_volumes(params)
self.assertEqual(1, len(fetched_vol), str(fetched_vol))
self.assertEqual(fetched_vol[0][self.name],
volume[self.name])
@@ -140,8 +136,7 @@
def test_volume_list_details_by_name(self):
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
params = {self.name: volume[self.name]}
- resp, fetched_vol = self.client.list_volumes_with_detail(params)
- self.assertEqual(200, resp.status)
+ _, fetched_vol = self.client.list_volumes_with_detail(params)
self.assertEqual(1, len(fetched_vol), str(fetched_vol))
self.assertEqual(fetched_vol[0][self.name],
volume[self.name])
@@ -149,8 +144,7 @@
@test.attr(type='gate')
def test_volumes_list_by_status(self):
params = {'status': 'available'}
- resp, fetched_list = self.client.list_volumes(params)
- self.assertEqual(200, resp.status)
+ _, fetched_list = self.client.list_volumes(params)
self._list_by_param_value_and_assert(params)
self.assertVolumesIn(fetched_list, self.volume_list,
fields=self.VOLUME_FIELDS)
@@ -158,8 +152,7 @@
@test.attr(type='gate')
def test_volumes_list_details_by_status(self):
params = {'status': 'available'}
- resp, fetched_list = self.client.list_volumes_with_detail(params)
- self.assertEqual(200, resp.status)
+ _, fetched_list = self.client.list_volumes_with_detail(params)
for volume in fetched_list:
self.assertEqual('available', volume['status'])
self.assertVolumesIn(fetched_list, self.volume_list)
@@ -169,8 +162,7 @@
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
zone = volume['availability_zone']
params = {'availability_zone': zone}
- resp, fetched_list = self.client.list_volumes(params)
- self.assertEqual(200, resp.status)
+ _, fetched_list = self.client.list_volumes(params)
self._list_by_param_value_and_assert(params)
self.assertVolumesIn(fetched_list, self.volume_list,
fields=self.VOLUME_FIELDS)
@@ -180,8 +172,7 @@
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
zone = volume['availability_zone']
params = {'availability_zone': zone}
- resp, fetched_list = self.client.list_volumes_with_detail(params)
- self.assertEqual(200, resp.status)
+ _, fetched_list = self.client.list_volumes_with_detail(params)
for volume in fetched_list:
self.assertEqual(zone, volume['availability_zone'])
self.assertVolumesIn(fetched_list, self.volume_list)
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 8bd4c88..5f0cffa 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -225,44 +225,38 @@
@test.attr(type=['negative', 'gate'])
def test_reserve_volume_with_negative_volume_status(self):
# Mark volume as reserved.
- resp, body = self.client.reserve_volume(self.volume['id'])
- self.assertEqual(202, resp.status)
+ _, body = self.client.reserve_volume(self.volume['id'])
# Mark volume which is marked as reserved before
self.assertRaises(exceptions.BadRequest,
self.client.reserve_volume,
self.volume['id'])
# Unmark volume as reserved.
- resp, body = self.client.unreserve_volume(self.volume['id'])
- self.assertEqual(202, resp.status)
+ _, body = self.client.unreserve_volume(self.volume['id'])
@test.attr(type=['negative', 'gate'])
def test_list_volumes_with_nonexistent_name(self):
v_name = data_utils.rand_name('Volume-')
params = {self.name_field: v_name}
- resp, fetched_volume = self.client.list_volumes(params)
- self.assertEqual(200, resp.status)
+ _, fetched_volume = self.client.list_volumes(params)
self.assertEqual(0, len(fetched_volume))
@test.attr(type=['negative', 'gate'])
def test_list_volumes_detail_with_nonexistent_name(self):
v_name = data_utils.rand_name('Volume-')
params = {self.name_field: v_name}
- resp, fetched_volume = self.client.list_volumes_with_detail(params)
- self.assertEqual(200, resp.status)
+ _, fetched_volume = self.client.list_volumes_with_detail(params)
self.assertEqual(0, len(fetched_volume))
@test.attr(type=['negative', 'gate'])
def test_list_volumes_with_invalid_status(self):
params = {'status': 'null'}
- resp, fetched_volume = self.client.list_volumes(params)
- self.assertEqual(200, resp.status)
+ _, fetched_volume = self.client.list_volumes(params)
self.assertEqual(0, len(fetched_volume))
@test.attr(type=['negative', 'gate'])
def test_list_volumes_detail_with_invalid_status(self):
params = {'status': 'null'}
- resp, fetched_volume = self.client.list_volumes_with_detail(params)
- self.assertEqual(200, resp.status)
+ _, fetched_volume = self.client.list_volumes_with_detail(params)
self.assertEqual(0, len(fetched_volume))
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 26316d2..7db1ef1 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -47,14 +47,13 @@
and validates result.
"""
if with_detail:
- resp, fetched_snap_list = \
+ _, fetched_snap_list = \
self.snapshots_client.\
list_snapshots_with_detail(params=params)
else:
- resp, fetched_snap_list = \
+ _, fetched_snap_list = \
self.snapshots_client.list_snapshots(params=params)
- self.assertEqual(200, resp.status)
# Validating params of fetched snapshots
for snap in fetched_snap_list:
for key in params:
@@ -74,9 +73,8 @@
self.addCleanup(self.servers_client.delete_server, server['id'])
self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
mountpoint = '/dev/%s' % CONF.compute.volume_device_name
- resp, body = self.volumes_client.attach_volume(
+ _, body = self.volumes_client.attach_volume(
self.volume_origin['id'], server['id'], mountpoint)
- self.assertEqual(202, resp.status)
self.volumes_client.wait_for_volume_status(self.volume_origin['id'],
'in-use')
self.addCleanup(self._detach, self.volume_origin['id'])
@@ -85,7 +83,6 @@
force=True)
# Delete the snapshot
self.snapshots_client.delete_snapshot(snapshot['id'])
- self.assertEqual(202, resp.status)
self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
self.snapshots.remove(snapshot)
@@ -97,40 +94,35 @@
display_name=s_name)
# Get the snap and check for some of its details
- resp, snap_get = self.snapshots_client.get_snapshot(snapshot['id'])
- self.assertEqual(200, resp.status)
+ _, snap_get = self.snapshots_client.get_snapshot(snapshot['id'])
self.assertEqual(self.volume_origin['id'],
snap_get['volume_id'],
"Referred volume origin mismatch")
# Compare also with the output from the list action
tracking_data = (snapshot['id'], snapshot['display_name'])
- resp, snaps_list = self.snapshots_client.list_snapshots()
- self.assertEqual(200, resp.status)
+ _, snaps_list = self.snapshots_client.list_snapshots()
snaps_data = [(f['id'], f['display_name']) for f in snaps_list]
self.assertIn(tracking_data, snaps_data)
# Updates snapshot with new values
new_s_name = data_utils.rand_name('new-snap')
new_desc = 'This is the new description of snapshot.'
- resp, update_snapshot = \
+ _, update_snapshot = \
self.snapshots_client.update_snapshot(snapshot['id'],
display_name=new_s_name,
display_description=new_desc)
# Assert response body for update_snapshot method
- self.assertEqual(200, resp.status)
self.assertEqual(new_s_name, update_snapshot['display_name'])
self.assertEqual(new_desc, update_snapshot['display_description'])
# Assert response body for get_snapshot method
- resp, updated_snapshot = \
+ _, updated_snapshot = \
self.snapshots_client.get_snapshot(snapshot['id'])
- self.assertEqual(200, resp.status)
self.assertEqual(new_s_name, updated_snapshot['display_name'])
self.assertEqual(new_desc, updated_snapshot['display_description'])
# Delete the snapshot
self.snapshots_client.delete_snapshot(snapshot['id'])
- self.assertEqual(200, resp.status)
self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
self.snapshots.remove(snapshot)
@@ -177,13 +169,12 @@
@test.attr(type='gate')
def test_volume_from_snapshot(self):
# Create a temporary snap using wrapper method from base, then
- # create a snap based volume, check resp code and deletes it
+ # create a snap based volume and deletes it
snapshot = self.create_snapshot(self.volume_origin['id'])
# NOTE(gfidente): size is required also when passing snapshot_id
- resp, volume = self.volumes_client.create_volume(
+ _, volume = self.volumes_client.create_volume(
size=1,
snapshot_id=snapshot['id'])
- self.assertEqual(200, resp.status)
self.volumes_client.wait_for_volume_status(volume['id'], 'available')
self.volumes_client.delete_volume(volume['id'])
self.volumes_client.wait_for_resource_deletion(volume['id'])
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index 7ca8599..3ae227d 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -42,7 +42,7 @@
cls.metadata = {'Type': 'work'}
for i in range(3):
volume = cls.create_volume(metadata=cls.metadata)
- resp, volume = cls.client.get_volume(volume['id'])
+ _, volume = cls.client.get_volume(volume['id'])
cls.volume_list.append(volume)
cls.volume_id_list.append(volume['id'])
@@ -50,7 +50,7 @@
def tearDownClass(cls):
# Delete the created volumes
for volid in cls.volume_id_list:
- resp, _ = cls.client.delete_volume(volid)
+ cls.client.delete_volume(volid)
cls.client.wait_for_resource_deletion(volid)
super(VolumesV2ListTestJSON, cls).tearDownClass()
@@ -66,8 +66,7 @@
'sort_dir': sort_dir,
'sort_key': sort_key
}
- resp, fetched_volume = self.client.list_volumes_with_detail(params)
- self.assertEqual(200, resp.status)
+ _, fetched_volume = self.client.list_volumes_with_detail(params)
self.assertEqual(limit, len(fetched_volume),
"The count of volumes is %s, expected:%s " %
(len(fetched_volume), limit))
diff --git a/tempest/api_schema/request/__init__.py b/tempest/api_schema/request/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/request/__init__.py
diff --git a/tempest/api_schema/request/compute/__init__.py b/tempest/api_schema/request/compute/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/request/compute/__init__.py
diff --git a/tempest/api_schema/request/compute/flavors.py b/tempest/api_schema/request/compute/flavors.py
new file mode 100644
index 0000000..8fe9e3a
--- /dev/null
+++ b/tempest/api_schema/request/compute/flavors.py
@@ -0,0 +1,53 @@
+# (c) 2014 Deutsche Telekom AG
+# 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.
+
+common_flavor_details = {
+ "name": "get-flavor-details",
+ "http-method": "GET",
+ "url": "flavors/%s",
+ "resources": [
+ {"name": "flavor", "expected_result": 404}
+ ]
+}
+
+common_flavor_list = {
+ "name": "list-flavors-with-detail",
+ "http-method": "GET",
+ "url": "flavors/detail",
+ "json-schema": {
+ "type": "object",
+ "properties": {
+ }
+ }
+}
+
+common_admin_flavor_create = {
+ "name": "flavor-create",
+ "http-method": "POST",
+ "admin_client": True,
+ "url": "flavors",
+ "default_result_code": 400,
+ "json-schema": {
+ "type": "object",
+ "properties": {
+ "name": {"type": "string"},
+ "ram": {"type": "integer", "minimum": 1},
+ "vcpus": {"type": "integer", "minimum": 1},
+ "disk": {"type": "integer"},
+ "id": {"type": "integer"},
+ "swap": {"type": "integer"},
+ "rxtx_factor": {"type": "integer"},
+ "OS-FLV-EXT-DATA:ephemeral": {"type": "integer"}
+ }
+ }
+}
diff --git a/tempest/api_schema/request/compute/servers.py b/tempest/api_schema/request/compute/servers.py
new file mode 100644
index 0000000..731649c
--- /dev/null
+++ b/tempest/api_schema/request/compute/servers.py
@@ -0,0 +1,36 @@
+# (c) 2014 Deutsche Telekom AG
+# 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.
+
+common_get_console_output = {
+ "name": "get-console-output",
+ "http-method": "POST",
+ "url": "servers/%s/action",
+ "resources": [
+ {"name": "server", "expected_result": 404}
+ ],
+ "json-schema": {
+ "type": "object",
+ "properties": {
+ "os-getConsoleOutput": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": ["integer", "string"],
+ "minimum": 0
+ }
+ }
+ }
+ },
+ "additionalProperties": False
+ }
+}
diff --git a/tempest/api_schema/request/compute/v2/__init__.py b/tempest/api_schema/request/compute/v2/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/request/compute/v2/__init__.py
diff --git a/tempest/api_schema/request/compute/v2/flavors.py b/tempest/api_schema/request/compute/v2/flavors.py
new file mode 100644
index 0000000..bc459ad
--- /dev/null
+++ b/tempest/api_schema/request/compute/v2/flavors.py
@@ -0,0 +1,39 @@
+# (c) 2014 Deutsche Telekom AG
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import copy
+
+from tempest.api_schema.request.compute import flavors
+
+flavors_details = copy.deepcopy(flavors.common_flavor_details)
+
+flavor_list = copy.deepcopy(flavors.common_flavor_list)
+
+flavor_create = copy.deepcopy(flavors.common_admin_flavor_create)
+
+flavor_list["json-schema"]["properties"] = {
+ "minRam": {
+ "type": "integer",
+ "results": {
+ "gen_none": 400,
+ "gen_string": 400
+ }
+ },
+ "minDisk": {
+ "type": "integer",
+ "results": {
+ "gen_none": 400,
+ "gen_string": 400
+ }
+ }
+}
diff --git a/tempest/api_schema/request/compute/v2/servers.py b/tempest/api_schema/request/compute/v2/servers.py
new file mode 100644
index 0000000..c9002ed
--- /dev/null
+++ b/tempest/api_schema/request/compute/v2/servers.py
@@ -0,0 +1,18 @@
+# (c) 2014 Deutsche Telekom AG
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import copy
+
+from tempest.api_schema.request.compute import servers
+
+get_console_output = copy.deepcopy(servers.common_get_console_output)
diff --git a/tempest/api_schema/request/compute/v3/__init__.py b/tempest/api_schema/request/compute/v3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/request/compute/v3/__init__.py
diff --git a/tempest/api_schema/request/compute/v3/flavors.py b/tempest/api_schema/request/compute/v3/flavors.py
new file mode 100644
index 0000000..b913aca
--- /dev/null
+++ b/tempest/api_schema/request/compute/v3/flavors.py
@@ -0,0 +1,37 @@
+# (c) 2014 Deutsche Telekom AG
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import copy
+
+from tempest.api_schema.request.compute import flavors
+
+flavors_details = copy.deepcopy(flavors.common_flavor_details)
+
+flavor_list = copy.deepcopy(flavors.common_flavor_list)
+
+flavor_list["json-schema"]["properties"] = {
+ "min_ram": {
+ "type": "integer",
+ "results": {
+ "gen_none": 400,
+ "gen_string": 400
+ }
+ },
+ "min_disk": {
+ "type": "integer",
+ "results": {
+ "gen_none": 400,
+ "gen_string": 400
+ }
+ }
+}
diff --git a/tempest/cli/simple_read_only/test_ceilometer.py b/tempest/cli/simple_read_only/test_ceilometer.py
index 1d2822d..b622dd4 100644
--- a/tempest/cli/simple_read_only/test_ceilometer.py
+++ b/tempest/cli/simple_read_only/test_ceilometer.py
@@ -39,15 +39,19 @@
raise cls.skipException(msg)
super(SimpleReadOnlyCeilometerClientTest, cls).setUpClass()
+ @test.services('telemetry')
def test_ceilometer_meter_list(self):
self.ceilometer('meter-list')
@test.attr(type='slow')
+ @test.services('telemetry')
def test_ceilometer_resource_list(self):
self.ceilometer('resource-list')
+ @test.services('telemetry')
def test_ceilometermeter_alarm_list(self):
self.ceilometer('alarm-list')
+ @test.services('telemetry')
def test_ceilometer_version(self):
self.ceilometer('', flags='--version')
diff --git a/tempest/clients.py b/tempest/clients.py
index 0edcdf4..2b8b6fb 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -50,6 +50,7 @@
from tempest.services.compute.json.limits_client import LimitsClientJSON
from tempest.services.compute.json.migrations_client import \
MigrationsClientJSON
+from tempest.services.compute.json.networks_client import NetworksClientJSON
from tempest.services.compute.json.quotas_client import QuotaClassesClientJSON
from tempest.services.compute.json.quotas_client import QuotasClientJSON
from tempest.services.compute.json.security_group_default_rules_client import \
@@ -426,6 +427,7 @@
self.migrations_client = MigrationsClientJSON(self.auth_provider)
self.security_group_default_rules_client = (
SecurityGroupDefaultRulesClientJSON(self.auth_provider))
+ self.networks_client = NetworksClientJSON(self.auth_provider)
class AltManager(Manager):
diff --git a/tempest/common/custom_matchers.py b/tempest/common/custom_matchers.py
index 996c365..7348a7d 100644
--- a/tempest/common/custom_matchers.py
+++ b/tempest/common/custom_matchers.py
@@ -13,6 +13,9 @@
# under the License.
import re
+from unittest import util
+
+from testtools import helpers
class ExistsAllResponseHeaders(object):
@@ -172,3 +175,54 @@
def get_details(self):
return {}
+
+
+class MatchesDictExceptForKeys(object):
+ """Matches two dictionaries. Verifies all items are equals except for those
+ identified by a list of keys.
+ """
+
+ def __init__(self, expected, excluded_keys=None):
+ self.expected = expected
+ self.excluded_keys = excluded_keys if excluded_keys is not None else []
+
+ def match(self, actual):
+ filtered_expected = helpers.dict_subtract(self.expected,
+ self.excluded_keys)
+ filtered_actual = helpers.dict_subtract(actual,
+ self.excluded_keys)
+ if filtered_actual != filtered_expected:
+ return DictMismatch(filtered_expected, filtered_actual)
+
+
+class DictMismatch(object):
+ """Mismatch between two dicts describes deltas"""
+
+ def __init__(self, expected, actual):
+ self.expected = expected
+ self.actual = actual
+ self.intersect = set(self.expected) & set(self.actual)
+ self.symmetric_diff = set(self.expected) ^ set(self.actual)
+
+ def describe(self):
+ msg = ""
+ if self.symmetric_diff:
+ only_expected = helpers.dict_subtract(self.expected, self.actual)
+ only_actual = helpers.dict_subtract(self.actual, self.expected)
+ if only_expected:
+ msg += "Only in expected:\n %s\n" % \
+ util.safe_repr(only_expected)
+ if only_actual:
+ msg += "Only in actual:\n %s\n" % \
+ util.safe_repr(only_actual)
+ diff_set = set(o for o in self.intersect if
+ self.expected[o] != self.actual[o])
+ if diff_set:
+ msg += "Differences:\n"
+ for o in diff_set:
+ msg += " %s: expected %s, actual %s\n" % (
+ o, self.expected[o], self.actual[o])
+ return msg
+
+ def get_details(self):
+ return {}
diff --git a/tempest/common/generator/valid_generator.py b/tempest/common/generator/valid_generator.py
index a99bbc0..0d7b398 100644
--- a/tempest/common/generator/valid_generator.py
+++ b/tempest/common/generator/valid_generator.py
@@ -24,7 +24,7 @@
@base.generator_type("string")
@base.simple_generator
def generate_valid_string(self, schema):
- size = schema.get("minLength", 0)
+ size = schema.get("minLength", 1)
# TODO(dkr mko): handle format and pattern
return "x" * size
diff --git a/tempest/config.py b/tempest/config.py
index af6dd7a..4836c63 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -347,7 +347,11 @@
cfg.BoolOpt('interface_attach',
default=True,
help='Does the test environment support dynamic network '
- 'interface attachment?')
+ 'interface attachment?'),
+ cfg.BoolOpt('snapshot',
+ default=True,
+ help='Does the test environment support creating snapshot '
+ 'images of running instances?')
]
@@ -1079,6 +1083,10 @@
DEFAULT_CONFIG_FILE = "tempest.conf"
+ def __getattr__(self, attr):
+ # Handles config options from the default group
+ return getattr(cfg.CONF, attr)
+
def _set_attrs(self):
self.auth = cfg.CONF.auth
self.compute = cfg.CONF.compute
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 203b653..76d82aa 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -78,6 +78,11 @@
return cls._get_credentials(cls.isolated_creds.get_primary_creds,
'user')
+ @classmethod
+ def admin_credentials(cls):
+ return cls._get_credentials(cls.isolated_creds.get_admin_creds,
+ 'identity_admin')
+
class OfficialClientTest(tempest.test.BaseTestCase):
"""
@@ -355,6 +360,22 @@
return secgroup
+ def rebuild_server(self, server, client=None, image=None,
+ preserve_ephemeral=False, wait=True,
+ rebuild_kwargs=None):
+ if client is None:
+ client = self.compute_client
+ if image is None:
+ image = CONF.compute.image_ref
+ rebuild_kwargs = rebuild_kwargs or {}
+
+ LOG.debug("Rebuilding server (name: %s, image: %s, preserve eph: %s)",
+ server.name, image, preserve_ephemeral)
+ server.rebuild(image, preserve_ephemeral=preserve_ephemeral,
+ **rebuild_kwargs)
+ if wait:
+ self.status_timeout(client.servers, server.id, 'ACTIVE')
+
def create_server(self, client=None, name=None, image=None, flavor=None,
wait_on_boot=True, wait_on_delete=True,
create_kwargs={}):
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 0059619..3ad5c69 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -23,7 +23,7 @@
LOG = logging.getLogger(__name__)
-class TestAggregatesBasicOps(manager.OfficialClientTest):
+class TestAggregatesBasicOps(manager.ScenarioTest):
"""
Creates an aggregate within an availability zone
Adds a host to the aggregate
@@ -33,74 +33,67 @@
Deletes aggregate
"""
@classmethod
+ def setUpClass(cls):
+ super(TestAggregatesBasicOps, cls).setUpClass()
+ cls.aggregates_client = cls.manager.aggregates_client
+ cls.hosts_client = cls.manager.hosts_client
+
+ @classmethod
def credentials(cls):
return cls.admin_credentials()
def _create_aggregate(self, **kwargs):
- aggregate = self.compute_client.aggregates.create(**kwargs)
+ _, aggregate = self.aggregates_client.create_aggregate(**kwargs)
+ self.addCleanup(self._delete_aggregate, aggregate)
aggregate_name = kwargs['name']
availability_zone = kwargs['availability_zone']
- self.assertEqual(aggregate.name, aggregate_name)
- self.assertEqual(aggregate.availability_zone, availability_zone)
- self.addCleanup(self._delete_aggregate, aggregate)
- LOG.debug("Aggregate %s created." % (aggregate.name))
+ self.assertEqual(aggregate['name'], aggregate_name)
+ self.assertEqual(aggregate['availability_zone'], availability_zone)
return aggregate
def _delete_aggregate(self, aggregate):
- self.compute_client.aggregates.delete(aggregate.id)
- LOG.debug("Aggregate %s deleted. " % (aggregate.name))
+ self.aggregates_client.delete_aggregate(aggregate['id'])
def _get_host_name(self):
- hosts = self.compute_client.hosts.list()
+ _, hosts = self.hosts_client.list_hosts()
self.assertTrue(len(hosts) >= 1)
- computes = [x for x in hosts if x.service == 'compute']
- return computes[0].host_name
+ computes = [x for x in hosts if x['service'] == 'compute']
+ return computes[0]['host_name']
- def _add_host(self, aggregate_name, host):
- aggregate = self.compute_client.aggregates.add_host(aggregate_name,
- host)
- self.addCleanup(self._remove_host, aggregate, host)
- self.assertIn(host, aggregate.hosts)
- LOG.debug("Host %s added to Aggregate %s." % (host, aggregate.name))
+ def _add_host(self, aggregate_id, host):
+ _, aggregate = self.aggregates_client.add_host(aggregate_id, host)
+ self.addCleanup(self._remove_host, aggregate['id'], host)
+ self.assertIn(host, aggregate['hosts'])
- def _remove_host(self, aggregate_name, host):
- aggregate = self.compute_client.aggregates.remove_host(aggregate_name,
- host)
- self.assertNotIn(host, aggregate.hosts)
- LOG.debug("Host %s removed to Aggregate %s." % (host, aggregate.name))
+ def _remove_host(self, aggregate_id, host):
+ _, aggregate = self.aggregates_client.remove_host(aggregate_id, host)
+ self.assertNotIn(host, aggregate['hosts'])
def _check_aggregate_details(self, aggregate, aggregate_name, azone,
hosts, metadata):
- aggregate = self.compute_client.aggregates.get(aggregate.id)
- self.assertEqual(aggregate_name, aggregate.name)
- self.assertEqual(azone, aggregate.availability_zone)
- self.assertEqual(aggregate.hosts, hosts)
+ _, aggregate = self.aggregates_client.get_aggregate(aggregate['id'])
+ self.assertEqual(aggregate_name, aggregate['name'])
+ self.assertEqual(azone, aggregate['availability_zone'])
+ self.assertEqual(hosts, aggregate['hosts'])
for meta_key in metadata.keys():
- self.assertIn(meta_key, aggregate.metadata)
- self.assertEqual(metadata[meta_key], aggregate.metadata[meta_key])
- LOG.debug("Aggregate %s details match." % aggregate.name)
+ self.assertIn(meta_key, aggregate['metadata'])
+ self.assertEqual(metadata[meta_key],
+ aggregate['metadata'][meta_key])
def _set_aggregate_metadata(self, aggregate, meta):
- aggregate = self.compute_client.aggregates.set_metadata(aggregate.id,
- meta)
+ _, aggregate = self.aggregates_client.set_metadata(aggregate['id'],
+ meta)
for key, value in meta.items():
- self.assertEqual(meta[key], aggregate.metadata[key])
- LOG.debug("Aggregate %s metadata updated successfully." %
- aggregate.name)
+ self.assertEqual(meta[key], aggregate['metadata'][key])
def _update_aggregate(self, aggregate, aggregate_name,
availability_zone):
- values = {}
- if aggregate_name:
- values.update({'name': aggregate_name})
- if availability_zone:
- values.update({'availability_zone': availability_zone})
- if values.keys():
- aggregate = self.compute_client.aggregates.update(aggregate.id,
- values)
- for key, values in values.items():
- self.assertEqual(getattr(aggregate, key), values)
+ _, aggregate = self.aggregates_client.update_aggregate(
+ aggregate['id'], name=aggregate_name,
+ availability_zone=availability_zone)
+ self.assertEqual(aggregate['name'], aggregate_name)
+ self.assertEqual(aggregate['availability_zone'], availability_zone)
return aggregate
@test.services('compute')
@@ -115,16 +108,17 @@
self._set_aggregate_metadata(aggregate, metadata)
host = self._get_host_name()
- self._add_host(aggregate, host)
+ self._add_host(aggregate['id'], host)
self._check_aggregate_details(aggregate, aggregate_name, az, [host],
metadata)
aggregate_name = data_utils.rand_name('renamed-aggregate-scenario')
- aggregate = self._update_aggregate(aggregate, aggregate_name, None)
+ # Updating the name alone. The az must be specified again otherwise
+ # the tempest client would send None in the put body
+ aggregate = self._update_aggregate(aggregate, aggregate_name, az)
- additional_metadata = {'foo': 'bar'}
- self._set_aggregate_metadata(aggregate, additional_metadata)
+ new_metadata = {'foo': 'bar'}
+ self._set_aggregate_metadata(aggregate, new_metadata)
- metadata.update(additional_metadata)
- self._check_aggregate_details(aggregate, aggregate.name, az, [host],
- metadata)
+ self._check_aggregate_details(aggregate, aggregate['name'], az,
+ [host], new_metadata)
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index f197c15..9ad6bc4 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -23,7 +23,7 @@
LOG = logging.getLogger(__name__)
-class BaremetalBasicOpsPXESSH(manager.BaremetalScenarioTest):
+class BaremetalBasicOps(manager.BaremetalScenarioTest):
"""
This smoke test tests the pxe_ssh Ironic driver. It follows this basic
set of operations:
@@ -35,10 +35,76 @@
* Verifies SSH connectivity using created keypair via fixed IP
* Associates a floating ip
* Verifies SSH connectivity using created keypair via floating IP
+ * Verifies instance rebuild with ephemeral partition preservation
* Deletes instance
* Monitors the associated Ironic node for power and
expected state transitions
"""
+ def rebuild_instance(self, preserve_ephemeral=False):
+ self.rebuild_server(self.instance,
+ preserve_ephemeral=preserve_ephemeral,
+ wait=False)
+
+ node = self.get_node(instance_id=self.instance.id)
+ self.instance = self.compute_client.servers.get(self.instance.id)
+
+ self.addCleanup_with_wait(self.compute_client.servers,
+ self.instance.id,
+ cleanup_callable=self.delete_wrapper,
+ cleanup_args=[self.instance])
+
+ # We should remain on the same node
+ self.assertEqual(self.node.uuid, node.uuid)
+ self.node = node
+
+ self.status_timeout(self.compute_client.servers, self.instance.id,
+ 'REBUILD')
+ self.status_timeout(self.compute_client.servers, self.instance.id,
+ 'ACTIVE')
+
+ def create_remote_file(self, client, filename):
+ """Create a file on the remote client connection.
+
+ After creating the file, force a filesystem sync. Otherwise,
+ if we issue a rebuild too quickly, the file may not exist.
+ """
+ client.exec_command('sudo touch ' + filename)
+ client.exec_command('sync')
+
+ def verify_partition(self, client, label, mount, gib_size):
+ """Verify a labeled partition's mount point and size."""
+ LOG.info("Looking for partition %s mounted on %s" % (label, mount))
+
+ # Validate we have a device with the given partition label
+ cmd = "/sbin/blkid | grep '%s' | cut -d':' -f1" % label
+ device = client.exec_command(cmd).rstrip('\n')
+ LOG.debug("Partition device is %s" % device)
+ self.assertNotEqual('', device)
+
+ # Validate the mount point for the device
+ cmd = "mount | grep '%s' | cut -d' ' -f3" % device
+ actual_mount = client.exec_command(cmd).rstrip('\n')
+ LOG.debug("Partition mount point is %s" % actual_mount)
+ self.assertEqual(actual_mount, mount)
+
+ # Validate the partition size matches what we expect
+ numbers = '0123456789'
+ devnum = device.replace('/dev/', '')
+ cmd = "cat /sys/block/%s/%s/size" % (devnum.rstrip(numbers), devnum)
+ num_bytes = client.exec_command(cmd).rstrip('\n')
+ num_bytes = int(num_bytes) * 512
+ actual_gib_size = num_bytes / (1024 * 1024 * 1024)
+ LOG.debug("Partition size is %d GiB" % actual_gib_size)
+ self.assertEqual(actual_gib_size, gib_size)
+
+ def get_flavor_ephemeral_size(self):
+ """Returns size of the ephemeral partition in GiB."""
+ f_id = self.instance.flavor['id']
+ ephemeral = self.compute_client.flavors.get(f_id).ephemeral
+ if ephemeral != 'N/A':
+ return int(ephemeral)
+ return None
+
def add_floating_ip(self):
floating_ip = self.compute_client.floating_ips.create()
self.instance.add_floating_ip(floating_ip)
@@ -53,10 +119,32 @@
@test.services('baremetal', 'compute', 'image', 'network')
def test_baremetal_server_ops(self):
+ test_filename = '/mnt/rebuild_test.txt'
self.add_keypair()
self.boot_instance()
self.validate_ports()
self.verify_connectivity()
floating_ip = self.add_floating_ip()
self.verify_connectivity(ip=floating_ip)
+
+ vm_client = self.get_remote_client(self.instance)
+
+ # We expect the ephemeral partition to be mounted on /mnt and to have
+ # the same size as our flavor definition.
+ eph_size = self.get_flavor_ephemeral_size()
+ self.assertIsNotNone(eph_size)
+ self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
+
+ # Create the test file
+ self.create_remote_file(vm_client, test_filename)
+
+ # Rebuild and preserve the ephemeral partition
+ self.rebuild_instance(True)
+ self.verify_connectivity()
+
+ # Check that we maintained our data
+ vm_client = self.get_remote_client(self.instance)
+ self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
+ vm_client.exec_command('ls ' + test_filename)
+
self.terminate_instance()
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index fc6c66c..bba034b 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -22,6 +22,7 @@
from tempest.common import debug
from tempest.common.utils import data_utils
from tempest import config
+from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest.scenario import manager
from tempest import test
@@ -222,23 +223,31 @@
self.addCleanup(self.delete_wrapper, server)
def check_ports():
- port_list = [port for port in
- self._list_ports(device_id=server.id)
- if port != old_port]
- return len(port_list) == 1
+ self.new_port_list = [port for port in
+ self._list_ports(device_id=server.id)
+ if port != old_port]
+ return len(self.new_port_list) == 1
- test.call_until_true(check_ports, 60, 1)
- new_port_list = [p for p in
- self._list_ports(device_id=server.id)
- if p != old_port]
- self.assertEqual(1, len(new_port_list))
- new_port = new_port_list[0]
+ if not test.call_until_true(check_ports, CONF.network.build_timeout,
+ CONF.network.build_interval):
+ raise exceptions.TimeoutException("No new port attached to the "
+ "server in time (%s sec) !"
+ % CONF.network.build_timeout)
new_port = net_common.DeletablePort(client=self.network_client,
- **new_port)
- new_nic_list = self._get_server_nics(ssh_client)
- diff_list = [n for n in new_nic_list if n not in old_nic_list]
- self.assertEqual(1, len(diff_list))
- num, new_nic = diff_list[0]
+ **self.new_port_list[0])
+
+ def check_new_nic():
+ new_nic_list = self._get_server_nics(ssh_client)
+ self.diff_list = [n for n in new_nic_list if n not in old_nic_list]
+ return len(self.diff_list) == 1
+
+ if not test.call_until_true(check_new_nic, CONF.network.build_timeout,
+ CONF.network.build_interval):
+ raise exceptions.TimeoutException("Interface not visible on the "
+ "guest after %s sec"
+ % CONF.network.build_timeout)
+
+ num, new_nic = self.diff_list[0]
ssh_client.assign_static_ip(nic=new_nic,
addr=new_port.fixed_ips[0]['ip_address'])
ssh_client.turn_nic_on(nic=new_nic)
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 8058b3d..ecb802f 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -213,10 +213,16 @@
myport = (tenant.router.id, tenant.subnet.id)
router_ports = [(i['device_id'], i['fixed_ips'][0]['subnet_id']) for i
in self.network_client.list_ports()['ports']
- if i['device_owner'] == 'network:router_interface']
+ if self._is_router_port(i)]
self.assertIn(myport, router_ports)
+ def _is_router_port(self, port):
+ """Return True if port is a router interface."""
+ # NOTE(armando-migliaccio): match device owner for both centralized
+ # and distributed routers; 'device_owner' is "" by default.
+ return port['device_owner'].startswith('network:router_interface')
+
def _create_server(self, name, tenant, security_groups=None):
"""
creates a server and assigns to security group
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index 7dd662d..ffdd006 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
from tempest import config
from tempest.openstack.common import log
from tempest.scenario import manager
@@ -71,6 +73,8 @@
def _set_floating_ip_to_server(self, server, floating_ip):
server.add_floating_ip(floating_ip)
+ @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
+ 'Snapshotting is not available.')
@test.services('compute', 'network', 'image')
def test_snapshot_pattern(self):
# prepare for booting a instance
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index be27024..4783273 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -16,6 +16,7 @@
import time
from cinderclient import exceptions as cinder_exceptions
+import testtools
from tempest.common.utils import data_utils
from tempest import config
@@ -150,6 +151,8 @@
self.assertEqual(self.timestamp, got_timestamp)
@tempest.test.skip_because(bug="1205344")
+ @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
+ 'Snapshotting is not available.')
@tempest.test.services('compute', 'network', 'volume', 'image')
def test_stamp_pattern(self):
# prepare for booting a instance
diff --git a/tempest/services/compute/json/networks_client.py b/tempest/services/compute/json/networks_client.py
new file mode 100644
index 0000000..40eb1a6
--- /dev/null
+++ b/tempest/services/compute/json/networks_client.py
@@ -0,0 +1,40 @@
+# 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.common import rest_client
+from tempest import config
+
+CONF = config.CONF
+
+
+class NetworksClientJSON(rest_client.RestClient):
+
+ def __init__(self, auth_provider):
+ super(NetworksClientJSON, self).__init__(auth_provider)
+ self.service = CONF.compute.catalog_type
+
+ def list_networks(self):
+ resp, body = self.get("os-networks")
+ body = json.loads(body)
+ self.expected_success(200, resp.status)
+ return resp, body['networks']
+
+ def get_network(self, network_id):
+ resp, body = self.get("os-networks/%s" % str(network_id))
+ body = json.loads(body)
+ self.expected_success(200, resp.status)
+ return resp, body['network']
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py
index 4a7c163..bc5e04a 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/image_client.py
@@ -235,7 +235,7 @@
def is_resource_deleted(self, id):
try:
- self.get_image(id)
+ self.get_image_meta(id)
except exceptions.NotFound:
return True
return False
diff --git a/tempest/services/volume/json/admin/volume_hosts_client.py b/tempest/services/volume/json/admin/volume_hosts_client.py
index 84e4705..b3a22b5 100644
--- a/tempest/services/volume/json/admin/volume_hosts_client.py
+++ b/tempest/services/volume/json/admin/volume_hosts_client.py
@@ -43,4 +43,5 @@
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['hosts']
diff --git a/tempest/services/volume/json/admin/volume_quotas_client.py b/tempest/services/volume/json/admin/volume_quotas_client.py
index 7b3e5de..90790e3 100644
--- a/tempest/services/volume/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/json/admin/volume_quotas_client.py
@@ -42,6 +42,7 @@
url = 'os-quota-sets/%s/defaults' % tenant_id
resp, body = self.get(url)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def get_quota_set(self, tenant_id, params=None):
@@ -52,12 +53,14 @@
url += '?%s' % urllib.urlencode(params)
resp, body = self.get(url)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def get_quota_usage(self, tenant_id):
"""List the quota set for a tenant."""
resp, body = self.get_quota_set(tenant_id, params={'usage': True})
+ self.expected_success(200, resp.status)
return resp, body
def update_quota_set(self, tenant_id, gigabytes=None, volumes=None,
@@ -75,8 +78,10 @@
post_body = jsonutils.dumps({'quota_set': post_body})
resp, body = self.put('os-quota-sets/%s' % tenant_id, post_body)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def delete_quota_set(self, tenant_id):
"""Delete the tenant's quota set."""
- return self.delete('os-quota-sets/%s' % tenant_id)
+ resp, body = self.delete('os-quota-sets/%s' % tenant_id)
+ self.expected_success(200, resp.status)
diff --git a/tempest/services/volume/json/admin/volume_services_client.py b/tempest/services/volume/json/admin/volume_services_client.py
index d43c04a..c9b8bcc 100644
--- a/tempest/services/volume/json/admin/volume_services_client.py
+++ b/tempest/services/volume/json/admin/volume_services_client.py
@@ -35,4 +35,5 @@
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['services']
diff --git a/tempest/services/volume/json/admin/volume_types_client.py b/tempest/services/volume/json/admin/volume_types_client.py
index 65ecc67..44ef9fe 100644
--- a/tempest/services/volume/json/admin/volume_types_client.py
+++ b/tempest/services/volume/json/admin/volume_types_client.py
@@ -63,6 +63,7 @@
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['volume_types']
def get_volume_type(self, volume_id):
@@ -70,6 +71,7 @@
url = "types/%s" % str(volume_id)
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['volume_type']
def create_volume_type(self, name, **kwargs):
@@ -87,11 +89,13 @@
post_body = json.dumps({'volume_type': post_body})
resp, body = self.post('types', post_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['volume_type']
def delete_volume_type(self, volume_id):
"""Deletes the Specified Volume_type."""
- return self.delete("types/%s" % str(volume_id))
+ resp, body = self.delete("types/%s" % str(volume_id))
+ self.expected_success(202, resp.status)
def list_volume_types_extra_specs(self, vol_type_id, params=None):
"""List all the volume_types extra specs created."""
@@ -101,6 +105,7 @@
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['extra_specs']
def get_volume_type_extra_specs(self, vol_type_id, extra_spec_name):
@@ -109,6 +114,7 @@
str(extra_spec_name))
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body
def create_volume_type_extra_specs(self, vol_type_id, extra_spec):
@@ -121,12 +127,14 @@
post_body = json.dumps({'extra_specs': extra_spec})
resp, body = self.post(url, post_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['extra_specs']
def delete_volume_type_extra_specs(self, vol_id, extra_spec_name):
"""Deletes the Specified Volume_type extra spec."""
- return self.delete("types/%s/extra_specs/%s" % ((str(vol_id)),
- str(extra_spec_name)))
+ resp, body = self.delete("types/%s/extra_specs/%s" % (
+ (str(vol_id)), str(extra_spec_name)))
+ self.expected_success(202, resp.status)
def update_volume_type_extra_specs(self, vol_type_id, extra_spec_name,
extra_spec):
@@ -142,6 +150,7 @@
put_body = json.dumps(extra_spec)
resp, body = self.put(url, put_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body
def get_encryption_type(self, vol_type_id):
@@ -152,6 +161,7 @@
url = "/types/%s/encryption" % str(vol_type_id)
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body
def create_encryption_type(self, vol_type_id, **kwargs):
@@ -170,8 +180,11 @@
post_body = json.dumps({'encryption': post_body})
resp, body = self.post(url, post_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['encryption']
def delete_encryption_type(self, vol_type_id):
"""Delete the encryption type for the specified volume-type."""
- return self.delete("/types/%s/encryption/provider" % str(vol_type_id))
+ resp, body = self.delete(
+ "/types/%s/encryption/provider" % str(vol_type_id))
+ self.expected_success(202, resp.status)
diff --git a/tempest/services/volume/json/availability_zone_client.py b/tempest/services/volume/json/availability_zone_client.py
index f2e7c5c..5ad2287 100644
--- a/tempest/services/volume/json/availability_zone_client.py
+++ b/tempest/services/volume/json/availability_zone_client.py
@@ -31,6 +31,7 @@
def get_availability_zone_list(self):
resp, body = self.get('os-availability-zone')
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['availabilityZoneInfo']
diff --git a/tempest/services/volume/json/backups_client.py b/tempest/services/volume/json/backups_client.py
index 183d06b..63fc646 100644
--- a/tempest/services/volume/json/backups_client.py
+++ b/tempest/services/volume/json/backups_client.py
@@ -47,6 +47,7 @@
post_body = json.dumps({'backup': post_body})
resp, body = self.post('backups', post_body)
body = json.loads(body)
+ self.expected_success(202, resp.status)
return resp, body['backup']
def restore_backup(self, backup_id, volume_id=None):
@@ -55,11 +56,13 @@
post_body = json.dumps({'restore': post_body})
resp, body = self.post('backups/%s/restore' % (backup_id), post_body)
body = json.loads(body)
+ self.expected_success(202, resp.status)
return resp, body['restore']
def delete_backup(self, backup_id):
"""Delete a backup of volume."""
resp, body = self.delete('backups/%s' % (str(backup_id)))
+ self.expected_success(202, resp.status)
return resp, body
def get_backup(self, backup_id):
@@ -67,6 +70,7 @@
url = "backups/%s" % str(backup_id)
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['backup']
def list_backups_with_detail(self):
@@ -74,6 +78,7 @@
url = "backups/detail"
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['backups']
def wait_for_backup_status(self, backup_id, status):
diff --git a/tempest/services/volume/json/extensions_client.py b/tempest/services/volume/json/extensions_client.py
index e3ff00b..c84b186 100644
--- a/tempest/services/volume/json/extensions_client.py
+++ b/tempest/services/volume/json/extensions_client.py
@@ -31,6 +31,7 @@
url = 'extensions'
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['extensions']
diff --git a/tempest/services/volume/json/snapshots_client.py b/tempest/services/volume/json/snapshots_client.py
index 2dff63d..f50ba2f 100644
--- a/tempest/services/volume/json/snapshots_client.py
+++ b/tempest/services/volume/json/snapshots_client.py
@@ -42,6 +42,7 @@
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['snapshots']
def list_snapshots_with_detail(self, params=None):
@@ -52,6 +53,7 @@
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['snapshots']
def get_snapshot(self, snapshot_id):
@@ -59,6 +61,7 @@
url = "snapshots/%s" % str(snapshot_id)
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['snapshot']
def create_snapshot(self, volume_id, **kwargs):
@@ -74,6 +77,7 @@
post_body = json.dumps({'snapshot': post_body})
resp, body = self.post('snapshots', post_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['snapshot']
def update_snapshot(self, snapshot_id, **kwargs):
@@ -81,6 +85,7 @@
put_body = json.dumps({'snapshot': kwargs})
resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['snapshot']
# NOTE(afazekas): just for the wait function
@@ -122,7 +127,8 @@
def delete_snapshot(self, snapshot_id):
"""Delete Snapshot."""
- return self.delete("snapshots/%s" % str(snapshot_id))
+ resp, body = self.delete("snapshots/%s" % str(snapshot_id))
+ self.expected_success(202, resp.status)
def is_resource_deleted(self, id):
try:
@@ -135,6 +141,7 @@
"""Reset the specified snapshot's status."""
post_body = json.dumps({'os-reset_status': {"status": status}})
resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def update_snapshot_status(self, snapshot_id, status, progress):
@@ -146,6 +153,7 @@
post_body = json.dumps({'os-update_snapshot_status': post_body})
url = 'snapshots/%s/action' % str(snapshot_id)
resp, body = self.post(url, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def create_snapshot_metadata(self, snapshot_id, metadata):
@@ -154,6 +162,7 @@
url = "snapshots/%s/metadata" % str(snapshot_id)
resp, body = self.post(url, put_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['metadata']
def get_snapshot_metadata(self, snapshot_id):
@@ -161,6 +170,7 @@
url = "snapshots/%s/metadata" % str(snapshot_id)
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['metadata']
def update_snapshot_metadata(self, snapshot_id, metadata):
@@ -169,6 +179,7 @@
url = "snapshots/%s/metadata" % str(snapshot_id)
resp, body = self.put(url, put_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['metadata']
def update_snapshot_metadata_item(self, snapshot_id, id, meta_item):
@@ -177,16 +188,18 @@
url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
resp, body = self.put(url, put_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['meta']
def delete_snapshot_metadata_item(self, snapshot_id, id):
"""Delete metadata item for the snapshot."""
url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
resp, body = self.delete(url)
- return resp, body
+ self.expected_success(200, resp.status)
def force_delete_snapshot(self, snapshot_id):
"""Force Delete Snapshot."""
post_body = json.dumps({'os-force_delete': {}})
resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
+ self.expected_success(202, resp.status)
return resp, body
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index 6c97497..c3a9269 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -35,6 +35,7 @@
self.service = CONF.volume.catalog_type
self.build_interval = CONF.volume.build_interval
self.build_timeout = CONF.volume.build_timeout
+ self.create_resp = 200
def get_attachment_from_volume(self, volume):
"""Return the element 'attachment' from input volumes."""
@@ -48,6 +49,7 @@
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['volumes']
def list_volumes_with_detail(self, params=None):
@@ -58,6 +60,7 @@
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['volumes']
def get_volume(self, volume_id):
@@ -65,6 +68,7 @@
url = "volumes/%s" % str(volume_id)
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['volume']
def create_volume(self, size=None, **kwargs):
@@ -88,6 +92,7 @@
post_body = json.dumps({'volume': post_body})
resp, body = self.post('volumes', post_body)
body = json.loads(body)
+ self.expected_success(self.create_resp, resp.status)
return resp, body['volume']
def update_volume(self, volume_id, **kwargs):
@@ -95,11 +100,13 @@
put_body = json.dumps({'volume': kwargs})
resp, body = self.put('volumes/%s' % volume_id, put_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['volume']
def delete_volume(self, volume_id):
"""Deletes the Specified Volume."""
- return self.delete("volumes/%s" % str(volume_id))
+ resp, body = self.delete("volumes/%s" % str(volume_id))
+ self.expected_success(202, resp.status)
def upload_volume(self, volume_id, image_name, disk_format):
"""Uploads a volume in Glance."""
@@ -111,6 +118,7 @@
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
body = json.loads(body)
+ self.expected_success(202, resp.status)
return resp, body['os-volume_upload_image']
def attach_volume(self, volume_id, instance_uuid, mountpoint):
@@ -122,6 +130,7 @@
post_body = json.dumps({'os-attach': post_body})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def detach_volume(self, volume_id):
@@ -130,6 +139,7 @@
post_body = json.dumps({'os-detach': post_body})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def reserve_volume(self, volume_id):
@@ -138,6 +148,7 @@
post_body = json.dumps({'os-reserve': post_body})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def unreserve_volume(self, volume_id):
@@ -146,6 +157,7 @@
post_body = json.dumps({'os-unreserve': post_body})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def wait_for_volume_status(self, volume_id, status):
@@ -183,24 +195,30 @@
post_body = json.dumps({'os-extend': post_body})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def reset_volume_status(self, volume_id, status):
"""Reset the Specified Volume's Status."""
post_body = json.dumps({'os-reset_status': {"status": status}})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def volume_begin_detaching(self, volume_id):
"""Volume Begin Detaching."""
+ # ref cinder/api/contrib/volume_actions.py#L158
post_body = json.dumps({'os-begin_detaching': {}})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def volume_roll_detaching(self, volume_id):
"""Volume Roll Detaching."""
+ # cinder/api/contrib/volume_actions.py#L170
post_body = json.dumps({'os-roll_detaching': {}})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def create_volume_transfer(self, vol_id, display_name=None):
@@ -213,6 +231,7 @@
post_body = json.dumps({'transfer': post_body})
resp, body = self.post('os-volume-transfer', post_body)
body = json.loads(body)
+ self.expected_success(202, resp.status)
return resp, body['transfer']
def get_volume_transfer(self, transfer_id):
@@ -220,6 +239,7 @@
url = "os-volume-transfer/%s" % str(transfer_id)
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['transfer']
def list_volume_transfers(self, params=None):
@@ -229,11 +249,13 @@
url += '?%s' % urllib.urlencode(params)
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['transfers']
def delete_volume_transfer(self, transfer_id):
"""Delete a volume transfer."""
- return self.delete("os-volume-transfer/%s" % str(transfer_id))
+ resp, body = self.delete("os-volume-transfer/%s" % str(transfer_id))
+ self.expected_success(202, resp.status)
def accept_volume_transfer(self, transfer_id, transfer_auth_key):
"""Accept a volume transfer."""
@@ -244,6 +266,7 @@
post_body = json.dumps({'accept': post_body})
resp, body = self.post(url, post_body)
body = json.loads(body)
+ self.expected_success(202, resp.status)
return resp, body['transfer']
def update_volume_readonly(self, volume_id, readonly):
@@ -254,12 +277,14 @@
post_body = json.dumps({'os-update_readonly_flag': post_body})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def force_delete_volume(self, volume_id):
"""Force Delete Volume."""
post_body = json.dumps({'os-force_delete': {}})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
+ self.expected_success(202, resp.status)
return resp, body
def create_volume_metadata(self, volume_id, metadata):
@@ -268,6 +293,7 @@
url = "volumes/%s/metadata" % str(volume_id)
resp, body = self.post(url, put_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['metadata']
def get_volume_metadata(self, volume_id):
@@ -275,6 +301,7 @@
url = "volumes/%s/metadata" % str(volume_id)
resp, body = self.get(url)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['metadata']
def update_volume_metadata(self, volume_id, metadata):
@@ -283,6 +310,7 @@
url = "volumes/%s/metadata" % str(volume_id)
resp, body = self.put(url, put_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['metadata']
def update_volume_metadata_item(self, volume_id, id, meta_item):
@@ -291,13 +319,14 @@
url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
resp, body = self.put(url, put_body)
body = json.loads(body)
+ self.expected_success(200, resp.status)
return resp, body['meta']
def delete_volume_metadata_item(self, volume_id, id):
"""Delete metadata item for the volume."""
url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
resp, body = self.delete(url)
- return resp, body
+ self.expected_success(200, resp.status)
class VolumesClientJSON(BaseVolumesClientJSON):
diff --git a/tempest/services/volume/v2/json/volumes_client.py b/tempest/services/volume/v2/json/volumes_client.py
index 1f16ead..ac4342e 100644
--- a/tempest/services/volume/v2/json/volumes_client.py
+++ b/tempest/services/volume/v2/json/volumes_client.py
@@ -25,3 +25,4 @@
super(VolumesV2ClientJSON, self).__init__(auth_provider)
self.api_version = "v2"
+ self.create_resp = 202
diff --git a/tempest/services/volume/v2/xml/volumes_client.py b/tempest/services/volume/v2/xml/volumes_client.py
index c1bcf6e..b3133af 100644
--- a/tempest/services/volume/v2/xml/volumes_client.py
+++ b/tempest/services/volume/v2/xml/volumes_client.py
@@ -30,6 +30,7 @@
super(VolumesV2ClientXML, self).__init__(auth_provider)
self.api_version = "v2"
+ self.create_resp = 202
def _parse_volume(self, body):
vol = dict((attr, body.get(attr)) for attr in body.keys())
@@ -61,6 +62,7 @@
volumes += [self._parse_volume(vol) for vol in list(body)]
for v in volumes:
v = self._check_if_bootable(v)
+ self.expected_success(200, resp.status)
return resp, volumes
def get_volume(self, volume_id):
@@ -69,4 +71,5 @@
resp, body = self.get(url)
body = self._parse_volume(etree.fromstring(body))
body = self._check_if_bootable(body)
+ self.expected_success(200, resp.status)
return resp, body
diff --git a/tempest/services/volume/xml/admin/volume_hosts_client.py b/tempest/services/volume/xml/admin/volume_hosts_client.py
index 967c7c2..98a7c58 100644
--- a/tempest/services/volume/xml/admin/volume_hosts_client.py
+++ b/tempest/services/volume/xml/admin/volume_hosts_client.py
@@ -69,5 +69,6 @@
url += '?%s' % urllib.urlencode(params)
resp, body = self.get(url)
+ self.expected_success(200, resp.status)
body = self._parse_array(etree.fromstring(body))
return resp, body
diff --git a/tempest/services/volume/xml/admin/volume_quotas_client.py b/tempest/services/volume/xml/admin/volume_quotas_client.py
index a8c92fc..acf9102 100644
--- a/tempest/services/volume/xml/admin/volume_quotas_client.py
+++ b/tempest/services/volume/xml/admin/volume_quotas_client.py
@@ -48,6 +48,7 @@
"""List the quota set for a tenant."""
resp, body = self.get_quota_set(tenant_id, params={'usage': True})
+ self.expected_success(200, resp.status)
return resp, self._format_quota(body)
def update_quota_set(self, tenant_id, gigabytes=None, volumes=None,
@@ -68,8 +69,10 @@
resp, body = self.put('os-quota-sets/%s' % tenant_id,
str(xml.Document(element)))
body = xml.xml_to_json(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, self._format_quota(body)
def delete_quota_set(self, tenant_id):
"""Delete the tenant's quota set."""
- return self.delete('os-quota-sets/%s' % tenant_id)
+ resp, body = self.delete('os-quota-sets/%s' % tenant_id)
+ self.expected_success(200, resp.status)
diff --git a/tempest/services/volume/xml/admin/volume_services_client.py b/tempest/services/volume/xml/admin/volume_services_client.py
index 7bad16d..2ecb590 100644
--- a/tempest/services/volume/xml/admin/volume_services_client.py
+++ b/tempest/services/volume/xml/admin/volume_services_client.py
@@ -39,4 +39,5 @@
resp, body = self.get(url)
node = etree.fromstring(body)
body = [xml_utils.xml_to_json(x) for x in node.getchildren()]
+ self.expected_success(200, resp.status)
return resp, body
diff --git a/tempest/services/volume/xml/admin/volume_types_client.py b/tempest/services/volume/xml/admin/volume_types_client.py
index 90897ee..679d097 100644
--- a/tempest/services/volume/xml/admin/volume_types_client.py
+++ b/tempest/services/volume/xml/admin/volume_types_client.py
@@ -75,6 +75,7 @@
if body is not None:
volume_types += [self._parse_volume_type(vol)
for vol in list(body)]
+ self.expected_success(200, resp.status)
return resp, volume_types
def get_volume_type(self, type_id):
@@ -82,6 +83,7 @@
url = "types/%s" % str(type_id)
resp, body = self.get(url)
body = etree.fromstring(body)
+ self.expected_success(200, resp.status)
return resp, self._parse_volume_type(body)
def create_volume_type(self, name, **kwargs):
@@ -107,11 +109,13 @@
resp, body = self.post('types', str(common.Document(vol_type)))
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def delete_volume_type(self, type_id):
"""Deletes the Specified Volume_type."""
- return self.delete("types/%s" % str(type_id))
+ resp, body = self.delete("types/%s" % str(type_id))
+ self.expected_success(202, resp.status)
def list_volume_types_extra_specs(self, vol_type_id, params=None):
"""List all the volume_types extra specs created."""
@@ -126,6 +130,7 @@
if body is not None:
extra_specs += [self._parse_volume_type_extra_specs(spec)
for spec in list(body)]
+ self.expected_success(200, resp.status)
return resp, extra_specs
def get_volume_type_extra_specs(self, vol_type_id, extra_spec_name):
@@ -134,6 +139,7 @@
str(extra_spec_name))
resp, body = self.get(url)
body = etree.fromstring(body)
+ self.expected_success(200, resp.status)
return resp, self._parse_volume_type_extra_specs(body)
def create_volume_type_extra_specs(self, vol_type_id, extra_spec):
@@ -158,12 +164,15 @@
resp, body = self.post(url, str(common.Document(extra_specs)))
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def delete_volume_type_extra_specs(self, vol_id, extra_spec_name):
"""Deletes the Specified Volume_type extra spec."""
- return self.delete("types/%s/extra_specs/%s" % ((str(vol_id)),
- str(extra_spec_name)))
+ resp, body = self.delete("types/%s/extra_specs/%s" % (
+ (str(vol_id)), str(extra_spec_name)))
+ self.expected_success(202, resp.status)
+ return resp, body
def update_volume_type_extra_specs(self, vol_type_id, extra_spec_name,
extra_spec):
@@ -187,6 +196,7 @@
resp, body = self.put(url, str(common.Document(extra_specs)))
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def is_resource_deleted(self, id):
diff --git a/tempest/services/volume/xml/availability_zone_client.py b/tempest/services/volume/xml/availability_zone_client.py
index a883ef5..b956d3f 100644
--- a/tempest/services/volume/xml/availability_zone_client.py
+++ b/tempest/services/volume/xml/availability_zone_client.py
@@ -36,6 +36,7 @@
def get_availability_zone_list(self):
resp, body = self.get('os-availability-zone')
availability_zone = self._parse_array(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, availability_zone
diff --git a/tempest/services/volume/xml/extensions_client.py b/tempest/services/volume/xml/extensions_client.py
index fe8b7cb..f2b2e02 100644
--- a/tempest/services/volume/xml/extensions_client.py
+++ b/tempest/services/volume/xml/extensions_client.py
@@ -39,6 +39,7 @@
url = 'extensions'
resp, body = self.get(url)
body = self._parse_array(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
diff --git a/tempest/services/volume/xml/snapshots_client.py b/tempest/services/volume/xml/snapshots_client.py
index 4b1ba25..7636707 100644
--- a/tempest/services/volume/xml/snapshots_client.py
+++ b/tempest/services/volume/xml/snapshots_client.py
@@ -49,6 +49,7 @@
snapshots = []
for snap in body:
snapshots.append(common.xml_to_json(snap))
+ self.expected_success(200, resp.status)
return resp, snapshots
def list_snapshots_with_detail(self, params=None):
@@ -63,6 +64,7 @@
snapshots = []
for snap in body:
snapshots.append(common.xml_to_json(snap))
+ self.expected_success(200, resp.status)
return resp, snapshots
def get_snapshot(self, snapshot_id):
@@ -70,6 +72,7 @@
url = "snapshots/%s" % str(snapshot_id)
resp, body = self.get(url)
body = etree.fromstring(body)
+ self.expected_success(200, resp.status)
return resp, common.xml_to_json(body)
def create_snapshot(self, volume_id, **kwargs):
@@ -87,6 +90,7 @@
resp, body = self.post('snapshots',
str(common.Document(snapshot)))
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def update_snapshot(self, snapshot_id, **kwargs):
@@ -96,6 +100,7 @@
resp, body = self.put('snapshots/%s' % snapshot_id,
str(common.Document(put_body)))
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
# NOTE(afazekas): just for the wait function
@@ -137,7 +142,8 @@
def delete_snapshot(self, snapshot_id):
"""Delete Snapshot."""
- return self.delete("snapshots/%s" % str(snapshot_id))
+ resp, body = self.delete("snapshots/%s" % str(snapshot_id))
+ self.expected_success(202, resp.status)
def is_resource_deleted(self, id):
try:
@@ -153,6 +159,7 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
def update_snapshot_status(self, snapshot_id, status, progress):
@@ -165,6 +172,7 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
def _metadata_body(self, meta):
@@ -188,6 +196,7 @@
resp, body = self.post('snapshots/%s/metadata' % snapshot_id,
str(common.Document(post_body)))
body = self._parse_key_value(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def get_snapshot_metadata(self, snapshot_id):
@@ -195,6 +204,7 @@
url = "snapshots/%s/metadata" % str(snapshot_id)
resp, body = self.get(url)
body = self._parse_key_value(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def update_snapshot_metadata(self, snapshot_id, metadata):
@@ -203,6 +213,7 @@
url = "snapshots/%s/metadata" % str(snapshot_id)
resp, body = self.put(url, str(common.Document(put_body)))
body = self._parse_key_value(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def update_snapshot_metadata_item(self, snapshot_id, id, meta_item):
@@ -213,12 +224,15 @@
url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
resp, body = self.put(url, str(common.Document(put_body)))
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def delete_snapshot_metadata_item(self, snapshot_id, id):
"""Delete metadata item for the snapshot."""
url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
- return self.delete(url)
+ resp, body = self.delete(url)
+ self.expected_success(200, resp.status)
+ return resp, body
def force_delete_snapshot(self, snapshot_id):
"""Force Delete Snapshot."""
@@ -227,4 +241,5 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
diff --git a/tempest/services/volume/xml/volumes_client.py b/tempest/services/volume/xml/volumes_client.py
index 89947fb..a8c1ae5 100644
--- a/tempest/services/volume/xml/volumes_client.py
+++ b/tempest/services/volume/xml/volumes_client.py
@@ -43,6 +43,7 @@
self.service = CONF.volume.catalog_type
self.build_interval = CONF.compute.build_interval
self.build_timeout = CONF.compute.build_timeout
+ self.create_resp = 200
def _translate_attributes_to_json(self, volume):
volume_host_attr = '{' + VOLUME_HOST_NS + '}host'
@@ -114,6 +115,7 @@
volumes = []
if body is not None:
volumes += [self._parse_volume(vol) for vol in list(body)]
+ self.expected_success(200, resp.status)
return resp, volumes
def list_volumes_with_detail(self, params=None):
@@ -128,6 +130,7 @@
volumes = []
if body is not None:
volumes += [self._parse_volume(vol) for vol in list(body)]
+ self.expected_success(200, resp.status)
return resp, volumes
def get_volume(self, volume_id):
@@ -135,6 +138,7 @@
url = "volumes/%s" % str(volume_id)
resp, body = self.get(url)
body = self._parse_volume(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def create_volume(self, size=None, **kwargs):
@@ -176,6 +180,7 @@
resp, body = self.post('volumes', str(common.Document(volume)))
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(self.create_resp, resp.status)
return resp, body
def update_volume(self, volume_id, **kwargs):
@@ -185,11 +190,14 @@
resp, body = self.put('volumes/%s' % volume_id,
str(common.Document(put_body)))
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def delete_volume(self, volume_id):
"""Deletes the Specified Volume."""
- return self.delete("volumes/%s" % str(volume_id))
+ resp, body = self.delete("volumes/%s" % str(volume_id))
+ self.expected_success(202, resp.status)
+ return resp, body
def wait_for_volume_status(self, volume_id, status):
"""Waits for a Volume to reach a given status."""
@@ -228,6 +236,7 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
def detach_volume(self, volume_id):
@@ -237,6 +246,7 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
def upload_volume(self, volume_id, image_name, disk_format):
@@ -247,6 +257,7 @@
url = 'volumes/%s/action' % str(volume_id)
resp, body = self.post(url, str(common.Document(post_body)))
volume = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, volume
def extend_volume(self, volume_id, extend_size):
@@ -257,6 +268,7 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
def reset_volume_status(self, volume_id, status):
@@ -268,6 +280,7 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
def volume_begin_detaching(self, volume_id):
@@ -295,6 +308,7 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
def unreserve_volume(self, volume_id):
@@ -304,6 +318,7 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
def create_volume_transfer(self, vol_id, display_name=None):
@@ -315,6 +330,7 @@
resp, body = self.post('os-volume-transfer',
str(common.Document(post_body)))
volume = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, volume
def get_volume_transfer(self, transfer_id):
@@ -322,6 +338,7 @@
url = "os-volume-transfer/%s" % str(transfer_id)
resp, body = self.get(url)
volume = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, volume
def list_volume_transfers(self, params=None):
@@ -335,6 +352,7 @@
volumes = []
if body is not None:
volumes += [self._parse_volume_transfer(vol) for vol in list(body)]
+ self.expected_success(200, resp.status)
return resp, volumes
def _parse_volume_transfer(self, body):
@@ -348,7 +366,9 @@
def delete_volume_transfer(self, transfer_id):
"""Delete a volume transfer."""
- return self.delete("os-volume-transfer/%s" % str(transfer_id))
+ resp, body = self.delete("os-volume-transfer/%s" % str(transfer_id))
+ self.expected_success(202, resp.status)
+ return resp, body
def accept_volume_transfer(self, transfer_id, transfer_auth_key):
"""Accept a volume transfer."""
@@ -356,6 +376,7 @@
url = 'os-volume-transfer/%s/accept' % transfer_id
resp, body = self.post(url, str(common.Document(post_body)))
volume = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, volume
def update_volume_readonly(self, volume_id, readonly):
@@ -366,6 +387,7 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
def force_delete_volume(self, volume_id):
@@ -375,6 +397,7 @@
resp, body = self.post(url, str(common.Document(post_body)))
if body:
body = common.xml_to_json(etree.fromstring(body))
+ self.expected_success(202, resp.status)
return resp, body
def _metadata_body(self, meta):
@@ -399,6 +422,7 @@
resp, body = self.post('volumes/%s/metadata' % volume_id,
str(common.Document(post_body)))
body = self._parse_key_value(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def get_volume_metadata(self, volume_id):
@@ -406,6 +430,7 @@
url = "volumes/%s/metadata" % str(volume_id)
resp, body = self.get(url)
body = self._parse_key_value(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def update_volume_metadata(self, volume_id, metadata):
@@ -414,6 +439,7 @@
url = "volumes/%s/metadata" % str(volume_id)
resp, body = self.put(url, str(common.Document(put_body)))
body = self._parse_key_value(etree.fromstring(body))
+ self.expected_success(200, resp.status)
return resp, body
def update_volume_metadata_item(self, volume_id, id, meta_item):
@@ -423,13 +449,16 @@
put_body.append(common.Text(v))
url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
resp, body = self.put(url, str(common.Document(put_body)))
+ self.expected_success(200, resp.status)
body = common.xml_to_json(etree.fromstring(body))
return resp, body
def delete_volume_metadata_item(self, volume_id, id):
"""Delete metadata item for the volume."""
url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
- return self.delete(url)
+ resp, body = self.delete(url)
+ self.expected_success(200, resp.status)
+ return resp, body
class VolumesClientXML(BaseVolumesClientXML):
diff --git a/tempest/test.py b/tempest/test.py
index 1e67d18..59da2f9 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -107,7 +107,7 @@
'identity': True,
'object_storage': CONF.service_available.swift,
'dashboard': CONF.service_available.horizon,
- 'ceilometer': CONF.service_available.ceilometer,
+ 'telemetry': CONF.service_available.ceilometer,
'data_processing': CONF.service_available.sahara
}
diff --git a/tempest/tests/common/test_custom_matchers.py b/tempest/tests/common/test_custom_matchers.py
new file mode 100644
index 0000000..57217e3
--- /dev/null
+++ b/tempest/tests/common/test_custom_matchers.py
@@ -0,0 +1,66 @@
+# Copyright 2014 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.
+
+from tempest.common import custom_matchers
+from tempest.tests import base
+
+from testtools.tests.matchers import helpers
+
+
+class TestMatchesDictExceptForKeys(base.TestCase,
+ helpers.TestMatchersInterface):
+
+ matches_matcher = custom_matchers.MatchesDictExceptForKeys(
+ {'a': 1, 'b': 2, 'c': 3, 'd': 4}, ['c', 'd'])
+ matches_matches = [
+ {'a': 1, 'b': 2, 'c': 3, 'd': 4},
+ {'a': 1, 'b': 2, 'c': 5},
+ {'a': 1, 'b': 2},
+ ]
+ matches_mismatches = [
+ {},
+ {'foo': 1},
+ {'a': 1, 'b': 3},
+ {'a': 1, 'b': 2, 'foo': 1},
+ {'a': 1, 'b': None, 'foo': 1},
+ ]
+
+ str_examples = []
+ describe_examples = [
+ ("Only in expected:\n"
+ " {'a': 1, 'b': 2}\n",
+ {},
+ matches_matcher),
+ ("Only in expected:\n"
+ " {'a': 1, 'b': 2}\n"
+ "Only in actual:\n"
+ " {'foo': 1}\n",
+ {'foo': 1},
+ matches_matcher),
+ ("Differences:\n"
+ " b: expected 2, actual 3\n",
+ {'a': 1, 'b': 3},
+ matches_matcher),
+ ("Only in actual:\n"
+ " {'foo': 1}\n",
+ {'a': 1, 'b': 2, 'foo': 1},
+ matches_matcher),
+ ("Only in actual:\n"
+ " {'foo': 1}\n"
+ "Differences:\n"
+ " b: expected 2, actual None\n",
+ {'a': 1, 'b': None, 'foo': 1},
+ matches_matcher)
+ ]
\ No newline at end of file
diff --git a/tox.ini b/tox.ini
index b3d4397..edcb901 100644
--- a/tox.ini
+++ b/tox.ini
@@ -111,7 +111,8 @@
# H402 skipped because some docstrings aren't sentences
# E123 skipped because it is ignored by default in the default pep8
# E129 skipped because it is too limiting when combined with other rules
+# H305 skipped because it is inconsistent between python versions
# Skipped because of new hacking 0.9: H405,H904
-ignore = E125,H402,E123,E129,H404,H405,H904
+ignore = E125,H402,E123,E129,H404,H405,H904,H305
show-source = True
exclude = .git,.venv,.tox,dist,doc,openstack,*egg