Merge "Merge the separated link lines on image client"
diff --git a/releasenotes/notes/add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml b/releasenotes/notes/add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml
new file mode 100644
index 0000000..57bf47c
--- /dev/null
+++ b/releasenotes/notes/add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml
@@ -0,0 +1,6 @@
+---
+upgrade:
+  - Add an error translation to list_versions() of versions_client of both
+    compute and network. This can affect users who are expecting that these
+    clients return error status code instead of the exception. It is needed
+    to change the code for handling the exception like the other clients code.
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 7fd23fc..6c417f1 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -19,6 +19,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import test_utils
 from tempest import test
 
 CONF = config.CONF
@@ -75,6 +76,8 @@
         body = self.client.create_image(self.server_id, name=name,
                                         metadata=meta)
         image_id = data_utils.parse_image_id(body.response['location'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.client.delete_image, image_id)
         waiters.wait_for_image_status(self.client, image_id, 'ACTIVE')
 
         # Verify the image was created correctly
diff --git a/tempest/api/compute/servers/test_availability_zone.py b/tempest/api/compute/servers/test_availability_zone.py
index 76da317..00df86b 100644
--- a/tempest/api/compute/servers/test_availability_zone.py
+++ b/tempest/api/compute/servers/test_availability_zone.py
@@ -29,4 +29,4 @@
     def test_get_availability_zone_list_with_non_admin_user(self):
         # List of availability zone with non-administrator user
         availability_zone = self.client.list_availability_zones()
-        self.assertTrue(len(availability_zone['availabilityZoneInfo']) > 0)
+        self.assertGreater(len(availability_zone['availabilityZoneInfo']), 0)
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index c48169f..d4831b1 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -17,7 +17,6 @@
 
 from tempest.api.compute import base
 from tempest.common import compute
-from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
 from tempest.common import waiters
 from tempest import config
@@ -72,12 +71,8 @@
 
     def _create_and_attach_volume(self, server):
         # Create a volume and wait for it to become ready
-        vol_name = data_utils.rand_name(self.__class__.__name__ + '-volume')
-        volume = self.volumes_client.create_volume(
-            size=CONF.volume.volume_size, display_name=vol_name)['volume']
+        volume = self.create_volume()
         self.addCleanup(self.delete_volume, volume['id'])
-        waiters.wait_for_volume_status(self.volumes_client,
-                                       volume['id'], 'available')
 
         # Attach the volume to the server
         self.attachment = self.servers_client.attach_volume(
diff --git a/tempest/api/compute/volumes/test_volume_snapshots.py b/tempest/api/compute/volumes/test_volume_snapshots.py
index e96982d..460c882 100644
--- a/tempest/api/compute/volumes/test_volume_snapshots.py
+++ b/tempest/api/compute/volumes/test_volume_snapshots.py
@@ -40,13 +40,9 @@
 
     @test.idempotent_id('cd4ec87d-7825-450d-8040-6e2068f2da8f')
     def test_volume_snapshot_create_get_list_delete(self):
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        volume = self.volumes_client.create_volume(
-            size=CONF.volume.volume_size,
-            display_name=v_name)['volume']
+        volume = self.create_volume()
         self.addCleanup(self.delete_volume, volume['id'])
-        waiters.wait_for_volume_status(self.volumes_client, volume['id'],
-                                       'available')
+
         s_name = data_utils.rand_name(self.__class__.__name__ + '-Snapshot')
         # Create snapshot
         snapshot = self.snapshots_client.create_snapshot(
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index b5ef7c0..40793ec 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -32,6 +32,11 @@
     VOLUME_FIELDS = ('id', 'name')
 
     def assertVolumesIn(self, fetched_list, expected_list, fields=None):
+        """Check out the list.
+
+        This function is aim at check out whether all of the volumes in
+        expected_list are in fetched_list.
+        """
         if fields:
             fieldsgetter = operator.itemgetter(*fields)
             expected_list = map(fieldsgetter, expected_list)
@@ -58,7 +63,6 @@
     def resource_setup(cls):
         super(VolumesV2ListTestJSON, cls).resource_setup()
         cls.name = cls.VOLUME_FIELDS[1]
-
         # Create 3 test volumes
         cls.volume_list = []
         cls.metadata = {'Type': 'work'}
@@ -146,6 +150,28 @@
             self.assertEqual('available', volume['status'])
         self.assertVolumesIn(fetched_list, self.volume_list)
 
+    @test.idempotent_id('2016a942-3020-40d7-95ce-7613bf8407ce')
+    def test_volumes_list_by_bootable(self):
+        """Check out volumes.
+
+        This test function is aim at check out whether all of the volumes
+        in volume_list are not a bootable volume.
+        """
+        params = {'bootable': 'false'}
+        fetched_list = self.client.list_volumes(params=params)['volumes']
+        self._list_by_param_value_and_assert(params)
+        self.assertVolumesIn(fetched_list, self.volume_list,
+                             fields=self.VOLUME_FIELDS)
+
+    @test.idempotent_id('2016a939-72ec-482a-bf49-d5ca06216b9f')
+    def test_volumes_list_details_by_bootable(self):
+        params = {'bootable': 'false'}
+        fetched_list = self.client.list_volumes(
+            detail=True, params=params)['volumes']
+        for volume in fetched_list:
+            self.assertEqual('false', volume['bootable'])
+        self.assertVolumesIn(fetched_list, self.volume_list)
+
     @test.idempotent_id('c0cfa863-3020-40d7-b587-e35f597d5d87')
     def test_volumes_list_by_availability_zone(self):
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index 8507f8a..2d2771f 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -661,8 +661,7 @@
             time.sleep(delay)
             resp, resp_body = self._request(method, url,
                                             headers=headers, body=body)
-        self._error_checker(method, url, headers, body,
-                            resp, resp_body)
+        self._error_checker(resp, resp_body)
         return resp, resp_body
 
     def _get_retry_after_delay(self, resp):
@@ -710,8 +709,7 @@
             raise ValueError("Failed to parse date %s" % val)
         return time.mktime(parts)
 
-    def _error_checker(self, method, url,
-                       headers, body, resp, resp_body):
+    def _error_checker(self, resp, resp_body):
 
         # NOTE(mtreinish): Check for httplib response from glance_http. The
         # object can't be used here because importing httplib breaks httplib2.
diff --git a/tempest/lib/services/compute/versions_client.py b/tempest/lib/services/compute/versions_client.py
index eb4e7e9..b2052c3 100644
--- a/tempest/lib/services/compute/versions_client.py
+++ b/tempest/lib/services/compute/versions_client.py
@@ -40,6 +40,7 @@
     def list_versions(self):
         version_url = self._get_base_version_url()
         resp, body = self.raw_request(version_url, 'GET')
+        self._error_checker(resp, body)
         body = json.loads(body)
         self.validate_response(schema.list_versions, resp, body)
         return rest_client.ResponseBody(resp, body)
@@ -56,6 +57,7 @@
         # we need a token for this request
         resp, body = self.raw_request(version_url, 'GET',
                                       {'X-Auth-Token': self.token})
+        self._error_checker(resp, body)
         body = json.loads(body)
         self.validate_response(schema.get_one_version, resp, body)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/image/v1/images_client.py b/tempest/lib/services/image/v1/images_client.py
index 9737be3..e67a547 100644
--- a/tempest/lib/services/image/v1/images_client.py
+++ b/tempest/lib/services/image/v1/images_client.py
@@ -34,8 +34,7 @@
         data = iter(functools.partial(data.read, CHUNKSIZE), b'')
         resp, body = self.request('POST', 'images',
                                   headers=headers, body=data, chunked=True)
-        self._error_checker('POST', 'images', headers, data, resp,
-                            body)
+        self._error_checker(resp, body)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
@@ -47,8 +46,7 @@
         url = 'images/%s' % image_id
         resp, body = self.request('PUT', url, headers=headers,
                                   body=data, chunked=True)
-        self._error_checker('PUT', url, headers, data,
-                            resp, body)
+        self._error_checker(resp, body)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
diff --git a/tempest/lib/services/network/versions_client.py b/tempest/lib/services/network/versions_client.py
index 0202927..a9c3bbf 100644
--- a/tempest/lib/services/network/versions_client.py
+++ b/tempest/lib/services/network/versions_client.py
@@ -35,6 +35,7 @@
         start = time.time()
         self._log_request_start('GET', version_url)
         response, body = self.raw_request(version_url, 'GET')
+        self._error_checker(response, body)
         end = time.time()
         self._log_request('GET', version_url, response,
                           secs=(end - start), resp_body=body)
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index ec36fb7..9445e34 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -164,7 +164,7 @@
             chunked=True
         )
 
-        self._error_checker('PUT', None, headers, contents, resp, body)
+        self._error_checker(resp, body)
         self.expected_success(201, resp.status)
         return resp.status, resp.reason, resp
 
diff --git a/tempest/tests/lib/test_rest_client.py b/tempest/tests/lib/test_rest_client.py
index 057f57b..e6cf047 100644
--- a/tempest/tests/lib/test_rest_client.py
+++ b/tempest/tests/lib/test_rest_client.py
@@ -296,10 +296,6 @@
                                             status=int(r_code),
                                             body=json.dumps(resp_body))
         data = {
-            "method": "fake_method",
-            "url": "fake_url",
-            "headers": "fake_headers",
-            "body": "fake_body",
             "resp": resp,
             "resp_body": json.dumps(resp_body)
         }