Return complete response from compute images_client

Currently compute images_client returns Response by removing
top key from Response.
For example-
return service_client.ResponseBody(resp, body['image'])

As service clients are in direction to move to Tempest-lib, all
service clients should return Response without any truncation.
One good example is Resource pagination links which are lost with current
way of return value. Resource pagination links are present in parallel
(not inside) to top key of Response.

This patch makes compute images_client to return complete
Response body.

Change-Id: I57818ccf8d0f6a631223a240b20829e5c40c3e6d
Implements: blueprint method-return-value-and-move-service-clients-to-lib
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 894bfde..44dc555 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -287,7 +287,7 @@
         if 'wait_until' in kwargs:
             waiters.wait_for_image_status(cls.images_client,
                                           image_id, kwargs['wait_until'])
-            image = cls.images_client.show_image(image_id)
+            image = cls.images_client.show_image(image_id)['image']
 
             if kwargs['wait_until'] == 'ACTIVE':
                 if kwargs.get('wait_for_server', True):
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index d16c020..975b850 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -64,7 +64,8 @@
     def test_list_image_metadata(self):
         # All metadata key/value pairs for an image should be returned
         resp_metadata = self.client.list_image_metadata(self.image_id)
-        expected = {'os_version': 'value1', 'os_distro': 'value2'}
+        expected = {'metadata': {
+            'os_version': 'value1', 'os_distro': 'value2'}}
         self.assertEqual(expected, resp_metadata)
 
     @test.idempotent_id('ece7befc-d3ce-42a4-b4be-c3067a418c29')
@@ -74,7 +75,8 @@
         self.client.set_image_metadata(self.image_id,
                                        req_metadata)
 
-        resp_metadata = self.client.list_image_metadata(self.image_id)
+        resp_metadata = (self.client.list_image_metadata(self.image_id)
+                         ['metadata'])
         self.assertEqual(req_metadata, resp_metadata)
 
     @test.idempotent_id('7b491c11-a9d5-40fe-a696-7f7e03d3fea2')
@@ -85,16 +87,17 @@
                                           req_metadata)
 
         resp_metadata = self.client.list_image_metadata(self.image_id)
-        expected = {'os_version': 'alt1',
-                    'os_distro': 'value2',
-                    'architecture': 'value3'}
+        expected = {'metadata': {
+            'os_version': 'alt1',
+            'os_distro': 'value2',
+            'architecture': 'value3'}}
         self.assertEqual(expected, resp_metadata)
 
     @test.idempotent_id('4f5db52f-6685-4c75-b848-f4bb363f9aa6')
     def test_get_image_metadata_item(self):
         # The value for a specific metadata key should be returned
         meta = self.client.show_image_metadata_item(self.image_id,
-                                                    'os_distro')
+                                                    'os_distro')['meta']
         self.assertEqual('value2', meta['os_distro'])
 
     @test.idempotent_id('f2de776a-4778-4d90-a5da-aae63aee64ae')
@@ -105,7 +108,7 @@
         self.client.set_image_metadata_item(self.image_id,
                                             'os_version', meta)
         resp_metadata = self.client.list_image_metadata(self.image_id)
-        expected = {'os_version': 'alt', 'os_distro': 'value2'}
+        expected = {'metadata': {'os_version': 'alt', 'os_distro': 'value2'}}
         self.assertEqual(expected, resp_metadata)
 
     @test.idempotent_id('a013796c-ba37-4bb5-8602-d944511def14')
@@ -114,5 +117,5 @@
         self.client.delete_image_metadata_item(self.image_id,
                                                'os_version')
         resp_metadata = self.client.list_image_metadata(self.image_id)
-        expected = {'os_distro': 'value2'}
+        expected = {'metadata': {'os_distro': 'value2'}}
         self.assertEqual(expected, resp_metadata)
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 4f15ce1..37c2bb6 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -86,11 +86,11 @@
         waiters.wait_for_image_status(self.client, image_id, 'ACTIVE')
 
         # Verify the image was created correctly
-        image = self.client.show_image(image_id)
+        image = self.client.show_image(image_id)['image']
         self.assertEqual(name, image['name'])
         self.assertEqual('test', image['metadata']['image_type'])
 
-        original_image = self.client.show_image(self.image_ref)
+        original_image = self.client.show_image(self.image_ref)['image']
 
         # Verify minRAM is the same as the original image
         self.assertEqual(image['minRam'], original_image['minRam'])
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index 247a57b..9f3ba71 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -63,7 +63,7 @@
             image_file = six.StringIO(('*' * 1024))
             cls.glance_client.update_image(image_id, data=image_file)
             waiters.wait_for_image_status(cls.client, image_id, 'ACTIVE')
-            body = cls.client.show_image(image_id)
+            body = cls.client.show_image(image_id)['image']
             return body
 
         # Create non-snapshot images via glance
@@ -106,7 +106,7 @@
         # The list of images should contain only images with the
         # provided status
         params = {'status': 'ACTIVE'}
-        images = self.client.list_images(**params)
+        images = self.client.list_images(**params)['images']
 
         self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
         self.assertTrue(any([i for i in images if i['id'] == self.image2_id]))
@@ -117,7 +117,7 @@
         # List of all images should contain the expected images filtered
         # by name
         params = {'name': self.image1['name']}
-        images = self.client.list_images(**params)
+        images = self.client.list_images(**params)['images']
 
         self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
         self.assertFalse(any([i for i in images if i['id'] == self.image2_id]))
@@ -129,7 +129,7 @@
     def test_list_images_filter_by_server_id(self):
         # The images should contain images filtered by server id
         params = {'server': self.server1['id']}
-        images = self.client.list_images(**params)
+        images = self.client.list_images(**params)['images']
 
         self.assertTrue(any([i for i in images
                              if i['id'] == self.snapshot1_id]),
@@ -150,7 +150,7 @@
         # Try all server link types
         for link in server_links:
             params = {'server': link['href']}
-            images = self.client.list_images(**params)
+            images = self.client.list_images(**params)['images']
 
             self.assertFalse(any([i for i in images
                                   if i['id'] == self.snapshot1_id]))
@@ -165,7 +165,7 @@
     def test_list_images_filter_by_type(self):
         # The list of servers should be filtered by image type
         params = {'type': 'snapshot'}
-        images = self.client.list_images(**params)
+        images = self.client.list_images(**params)['images']
 
         self.assertTrue(any([i for i in images
                              if i['id'] == self.snapshot1_id]))
@@ -180,7 +180,7 @@
     def test_list_images_limit_results(self):
         # Verify only the expected number of results are returned
         params = {'limit': '1'}
-        images = self.client.list_images(**params)
+        images = self.client.list_images(**params)['images']
         self.assertEqual(1, len([x for x in images if 'id' in x]))
 
     @test.idempotent_id('18bac3ae-da27-436c-92a9-b22474d13aab')
@@ -190,7 +190,7 @@
         # Becoming ACTIVE will modify the updated time
         # Filter by the image's created time
         params = {'changes-since': self.image3['created']}
-        images = self.client.list_images(**params)
+        images = self.client.list_images(**params)['images']
         found = any([i for i in images if i['id'] == self.image3_id])
         self.assertTrue(found)
 
@@ -199,7 +199,7 @@
         # Detailed list of all images should only contain images
         # with the provided status
         params = {'status': 'ACTIVE'}
-        images = self.client.list_images(detail=True, **params)
+        images = self.client.list_images(detail=True, **params)['images']
 
         self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
         self.assertTrue(any([i for i in images if i['id'] == self.image2_id]))
@@ -210,7 +210,7 @@
         # Detailed list of all images should contain the expected
         # images filtered by name
         params = {'name': self.image1['name']}
-        images = self.client.list_images(detail=True, **params)
+        images = self.client.list_images(detail=True, **params)['images']
 
         self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
         self.assertFalse(any([i for i in images if i['id'] == self.image2_id]))
@@ -221,7 +221,7 @@
         # Verify only the expected number of results (with full details)
         # are returned
         params = {'limit': '1'}
-        images = self.client.list_images(detail=True, **params)
+        images = self.client.list_images(detail=True, **params)['images']
         self.assertEqual(1, len(images))
 
     @test.idempotent_id('8c78f822-203b-4bf6-8bba-56ebd551cf84')
@@ -234,7 +234,7 @@
         # Try all server link types
         for link in server_links:
             params = {'server': link['href']}
-            images = self.client.list_images(detail=True, **params)
+            images = self.client.list_images(detail=True, **params)['images']
 
             self.assertFalse(any([i for i in images
                                   if i['id'] == self.snapshot1_id]))
@@ -249,7 +249,7 @@
     def test_list_images_with_detail_filter_by_type(self):
         # The detailed list of servers should be filtered by image type
         params = {'type': 'snapshot'}
-        images = self.client.list_images(detail=True, **params)
+        images = self.client.list_images(detail=True, **params)['images']
         self.client.show_image(self.image_ref)
 
         self.assertTrue(any([i for i in images
@@ -268,5 +268,5 @@
         # Becoming ACTIVE will modify the updated time
         # Filter by the image's created time
         params = {'changes-since': self.image1['created']}
-        images = self.client.list_images(detail=True, **params)
+        images = self.client.list_images(detail=True, **params)['images']
         self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
diff --git a/tempest/api/compute/images/test_list_images.py b/tempest/api/compute/images/test_list_images.py
index b67378c..6ca15d6 100644
--- a/tempest/api/compute/images/test_list_images.py
+++ b/tempest/api/compute/images/test_list_images.py
@@ -37,19 +37,19 @@
     @test.idempotent_id('490d0898-e12a-463f-aef0-c50156b9f789')
     def test_get_image(self):
         # Returns the correct details for a single image
-        image = self.client.show_image(self.image_ref)
+        image = self.client.show_image(self.image_ref)['image']
         self.assertEqual(self.image_ref, image['id'])
 
     @test.idempotent_id('fd51b7f4-d4a3-4331-9885-866658112a6f')
     def test_list_images(self):
         # The list of all images should contain the image
-        images = self.client.list_images()
+        images = self.client.list_images()['images']
         found = any([i for i in images if i['id'] == self.image_ref])
         self.assertTrue(found)
 
     @test.idempotent_id('9f94cb6b-7f10-48c5-b911-a0b84d7d4cd6')
     def test_list_images_with_detail(self):
         # Detailed list of all images should contain the expected images
-        images = self.client.list_images(detail=True)
+        images = self.client.list_images(detail=True)['images']
         found = any([i for i in images if i['id'] == self.image_ref])
         self.assertTrue(found)
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 6160844..5c63557 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -44,7 +44,7 @@
 
         # Check to see if the alternate image ref actually exists...
         images_client = cls.images_client
-        images = images_client.list_images()
+        images = images_client.list_images()['images']
 
         if cls.image_ref != cls.image_ref_alt and \
             any([image for image in images
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 96a4502..6b3b661 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -456,7 +456,7 @@
         server = self.client.show_server(self.server_id)
         image_name = server['name'] + '-shelved'
         params = {'name': image_name}
-        images = self.images_client.list_images(**params)
+        images = self.images_client.list_images(**params)['images']
         self.assertEqual(1, len(images))
         self.assertEqual(image_name, images[0]['name'])
 
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 5a14418..8f81de0 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -480,7 +480,7 @@
         server = self.client.show_server(self.server_id)
         image_name = server['name'] + '-shelved'
         params = {'name': image_name}
-        images = self.images_client.list_images(**params)
+        images = self.images_client.list_images(**params)['images']
         self.assertEqual(1, len(images))
         self.assertEqual(image_name, images[0]['name'])
 
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index 7751c9a..b5a24c7 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -76,7 +76,7 @@
         body = cls.glance_client.update_image(image_id,
                                               data=image_file)['image']
         cls.glance_client.wait_for_image_status(image_id, 'active')
-        cls.image = cls.images_client.show_image(image_id)
+        cls.image = cls.images_client.show_image(image_id)['image']
 
         cls.keypairname = data_utils.rand_name('keypair')
         cls.keypairs_client.create_keypair(name=cls.keypairname)
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index a90f9ca..9db2321 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -131,7 +131,7 @@
     @test.idempotent_id('54a01030-c7fc-447c-86ee-c1182beae638')
     @test.services('image')
     def test_volume_create_get_update_delete_from_image(self):
-        image = self.images_client.show_image(CONF.compute.image_ref)
+        image = self.images_client.show_image(CONF.compute.image_ref)['image']
         min_disk = image.get('minDisk')
         disk_size = max(min_disk, CONF.volume.volume_size)
         self._volume_create_get_update_delete(
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 5e04c36..76d5d1c 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -770,7 +770,7 @@
 
     def list(self):
         client = self.client
-        images = client.list_images({"all_tenants": True})
+        images = client.list_images({"all_tenants": True})['images']
         if not self.is_save_state:
             images = [image for image in images if image['id']
                       not in self.saved_state_json['images'].keys()]
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 7aa4fc2..1a13bbd 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -123,11 +123,19 @@
     The client should also have build_interval and build_timeout attributes.
     """
     image = client.show_image(image_id)
+    # Compute image client return response wrapped in 'image' element
+    # which is not case with glance image client.
+    if 'image' in image:
+        image = image['image']
     start = int(time.time())
 
     while image['status'] != status:
         time.sleep(client.build_interval)
         image = client.show_image(image_id)
+        # Compute image client return response wrapped in 'image' element
+        # which is not case with glance image client.
+        if 'image' in image:
+            image = image['image']
         status_curr = image['status']
         if status_curr == 'ERROR':
             raise exceptions.AddImageException(image_id=image_id)
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index 41b3470..0a7d492 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -44,7 +44,7 @@
         self.flavors_client = os.flavors_client
 
     def ssh_user(self, image_id):
-        _image = self.images_client.show_image(image_id)
+        _image = self.images_client.show_image(image_id)['image']
         for regex, user in self.ssh_users:
             # First match wins
             if re.match(regex, _image['name']) is not None:
@@ -57,14 +57,14 @@
                              string=str(image['name']))
 
     def is_sshable_image(self, image_id):
-        _image = self.images_client.show_image(image_id)
+        _image = self.images_client.show_image(image_id)['image']
         return self._is_sshable_image(_image)
 
     def _is_flavor_enough(self, flavor, image):
         return image['minDisk'] <= flavor['disk']
 
     def is_flavor_enough(self, flavor_id, image_id):
-        _image = self.images_client.show_image(image_id)
+        _image = self.images_client.show_image(image_id)['image']
         _flavor = self.flavors_client.show_flavor(flavor_id)['flavor']
         return self._is_flavor_enough(_flavor, _image)
 
@@ -131,7 +131,7 @@
             return []
         if not hasattr(self, '_scenario_images'):
             try:
-                images = self.images_client.list_images()
+                images = self.images_client.list_images()['images']
                 self._scenario_images = [
                     (self._normalize_name(i['name']), dict(image_ref=i['id']))
                     for i in images if re.search(self.image_pattern,
diff --git a/tempest/services/compute/json/images_client.py b/tempest/services/compute/json/images_client.py
index 4e7e93f..99fdfe6 100644
--- a/tempest/services/compute/json/images_client.py
+++ b/tempest/services/compute/json/images_client.py
@@ -47,7 +47,7 @@
         resp, body = self.get(url)
         body = json.loads(body)
         self.validate_response(_schema, resp, body)
-        return service_client.ResponseBodyList(resp, body['images'])
+        return service_client.ResponseBody(resp, body)
 
     def show_image(self, image_id):
         """Returns the details of a single image."""
@@ -55,7 +55,7 @@
         self.expected_success(200, resp.status)
         body = json.loads(body)
         self.validate_response(schema.get_image, resp, body)
-        return service_client.ResponseBody(resp, body['image'])
+        return service_client.ResponseBody(resp, body)
 
     def delete_image(self, image_id):
         """Deletes the provided image."""
@@ -68,7 +68,7 @@
         resp, body = self.get("images/%s/metadata" % image_id)
         body = json.loads(body)
         self.validate_response(schema.image_metadata, resp, body)
-        return service_client.ResponseBody(resp, body['metadata'])
+        return service_client.ResponseBody(resp, body)
 
     def set_image_metadata(self, image_id, meta):
         """Sets the metadata for an image."""
@@ -76,7 +76,7 @@
         resp, body = self.put('images/%s/metadata' % image_id, post_body)
         body = json.loads(body)
         self.validate_response(schema.image_metadata, resp, body)
-        return service_client.ResponseBody(resp, body['metadata'])
+        return service_client.ResponseBody(resp, body)
 
     def update_image_metadata(self, image_id, meta):
         """Updates the metadata for an image."""
@@ -84,14 +84,14 @@
         resp, body = self.post('images/%s/metadata' % image_id, post_body)
         body = json.loads(body)
         self.validate_response(schema.image_metadata, resp, body)
-        return service_client.ResponseBody(resp, body['metadata'])
+        return service_client.ResponseBody(resp, body)
 
     def show_image_metadata_item(self, image_id, key):
         """Returns the value for a specific image metadata key."""
         resp, body = self.get("images/%s/metadata/%s" % (image_id, key))
         body = json.loads(body)
         self.validate_response(schema.image_meta_item, resp, body)
-        return service_client.ResponseBody(resp, body['meta'])
+        return service_client.ResponseBody(resp, body)
 
     def set_image_metadata_item(self, image_id, key, meta):
         """Sets the value for a specific image metadata key."""
@@ -100,7 +100,7 @@
                               post_body)
         body = json.loads(body)
         self.validate_response(schema.image_meta_item, resp, body)
-        return service_client.ResponseBody(resp, body['meta'])
+        return service_client.ResponseBody(resp, body)
 
     def delete_image_metadata_item(self, image_id, key):
         """Deletes a single image metadata key/value pair."""