diff options
author | Brian Rosmaita <rosmaita.fossdev@gmail.com> | 2018-08-14 21:01:22 -0400 |
---|---|---|
committer | Brian Rosmaita <rosmaita.fossdev@gmail.com> | 2018-08-14 21:01:22 -0400 |
commit | 432b9f6c24f8c4a121767b60a0f81eb2185d1ed5 (patch) | |
tree | 230b691cfd066d6a000746930b615c60432d7adf | |
parent | 89d9d59a6ebfd2969103ccaee564f597f7aec14b (diff) |
Add multihash checks to functional tests
Refactor the image functional tests to pull common code into a
utility function and add multihash checks to those functional tests
that are only checking that the legacy checksum is set correctly.
Change-Id: If4e2dbb6db2bee0b8d8e307ce2f7f7bd15cddea8
Notes
Notes (review):
Code-Review+1: Brin Zhang <zhangbailin@inspur.com>
Code-Review+2: Erno Kuvaja <jokke@usr.fi>
Code-Review+2: Abhishek Kekane <akekane@redhat.com>
Workflow+1: Abhishek Kekane <akekane@redhat.com>
Verified+2: Zuul
Submitted-by: Zuul
Submitted-at: Thu, 16 Aug 2018 08:08:34 +0000
Reviewed-on: https://review.openstack.org/591874
Project: openstack/glance
Branch: refs/heads/master
-rw-r--r-- | glance/tests/functional/ft_utils.py | 28 | ||||
-rw-r--r-- | glance/tests/functional/v2/test_images.py | 277 |
2 files changed, 143 insertions, 162 deletions
diff --git a/glance/tests/functional/ft_utils.py b/glance/tests/functional/ft_utils.py index ea0791d..edbfe5b 100644 --- a/glance/tests/functional/ft_utils.py +++ b/glance/tests/functional/ft_utils.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # License for the specific language governing permissions and limitations | 13 | # License for the specific language governing permissions and limitations |
14 | # under the License. | 14 | # under the License. |
15 | 15 | ||
16 | import six | ||
16 | import time | 17 | import time |
17 | 18 | ||
18 | from oslo_serialization import jsonutils | 19 | from oslo_serialization import jsonutils |
@@ -20,6 +21,33 @@ import requests | |||
20 | from six.moves import http_client as http | 21 | from six.moves import http_client as http |
21 | 22 | ||
22 | 23 | ||
24 | def verify_image_hashes_and_status( | ||
25 | test_obj, image_id, checksum=None, os_hash_value=None, status=None, | ||
26 | os_hash_algo='sha512'): | ||
27 | """Makes image-detail request and checks response. | ||
28 | |||
29 | :param test_obj: The test object; expected to have _url() and | ||
30 | _headers() defined on it | ||
31 | :param image_id: Image id to use in the request | ||
32 | :param checksum: Expected checksum (default: None) | ||
33 | :param os_hash_value: Expected multihash value (default: None) | ||
34 | :param status: Expected status (default: None) | ||
35 | :param os_hash_algo: Expected value of os_hash_algo; only checked when | ||
36 | os_hash_value is not None (default: 'sha512') | ||
37 | """ | ||
38 | path = test_obj._url('/v2/images/%s' % image_id) | ||
39 | response = requests.get(path, headers=test_obj._headers()) | ||
40 | test_obj.assertEqual(http.OK, response.status_code) | ||
41 | image = jsonutils.loads(response.text) | ||
42 | test_obj.assertEqual(checksum, image['checksum']) | ||
43 | if os_hash_value: | ||
44 | # make sure we're using the hashing_algorithm we expect | ||
45 | test_obj.assertEqual(six.text_type(os_hash_algo), | ||
46 | image['os_hash_algo']) | ||
47 | test_obj.assertEqual(os_hash_value, image['os_hash_value']) | ||
48 | test_obj.assertEqual(status, image['status']) | ||
49 | |||
50 | |||
23 | def wait_for_status(request_path, request_headers, status='active', | 51 | def wait_for_status(request_path, request_headers, status='active', |
24 | max_sec=10, delay_sec=0.2, start_delay_sec=None): | 52 | max_sec=10, delay_sec=0.2, start_delay_sec=None): |
25 | """ | 53 | """ |
diff --git a/glance/tests/functional/v2/test_images.py b/glance/tests/functional/v2/test_images.py index 11ce561..eb58436 100644 --- a/glance/tests/functional/v2/test_images.py +++ b/glance/tests/functional/v2/test_images.py | |||
@@ -189,20 +189,6 @@ class TestImages(functional.FunctionalTest): | |||
189 | self.assertEqual(1, len(images)) | 189 | self.assertEqual(1, len(images)) |
190 | self.assertEqual(image_id, images[0]['id']) | 190 | self.assertEqual(image_id, images[0]['id']) |
191 | 191 | ||
192 | def _verify_image_hashes_and_status( | ||
193 | checksum=None, os_hash_value=None, status=None): | ||
194 | path = self._url('/v2/images/%s' % image_id) | ||
195 | response = requests.get(path, headers=self._headers()) | ||
196 | self.assertEqual(http.OK, response.status_code) | ||
197 | image = jsonutils.loads(response.text) | ||
198 | self.assertEqual(checksum, image['checksum']) | ||
199 | if os_hash_value: | ||
200 | # make sure we're using the hashing_algorithm we expect | ||
201 | self.assertEqual(six.text_type('sha512'), | ||
202 | image['os_hash_algo']) | ||
203 | self.assertEqual(os_hash_value, image['os_hash_value']) | ||
204 | self.assertEqual(status, image['status']) | ||
205 | |||
206 | # Upload some image data to staging area | 192 | # Upload some image data to staging area |
207 | path = self._url('/v2/images/%s/stage' % image_id) | 193 | path = self._url('/v2/images/%s/stage' % image_id) |
208 | headers = self._headers({'Content-Type': 'application/octet-stream'}) | 194 | headers = self._headers({'Content-Type': 'application/octet-stream'}) |
@@ -211,7 +197,8 @@ class TestImages(functional.FunctionalTest): | |||
211 | self.assertEqual(http.NO_CONTENT, response.status_code) | 197 | self.assertEqual(http.NO_CONTENT, response.status_code) |
212 | 198 | ||
213 | # Verify image is in uploading state, hashes are None | 199 | # Verify image is in uploading state, hashes are None |
214 | _verify_image_hashes_and_status(status='uploading') | 200 | func_utils.verify_image_hashes_and_status(self, image_id, |
201 | status='uploading') | ||
215 | 202 | ||
216 | # Import image to store | 203 | # Import image to store |
217 | path = self._url('/v2/images/%s/import' % image_id) | 204 | path = self._url('/v2/images/%s/import' % image_id) |
@@ -236,9 +223,11 @@ class TestImages(functional.FunctionalTest): | |||
236 | delay_sec=0.2) | 223 | delay_sec=0.2) |
237 | expect_c = six.text_type(hashlib.md5(image_data).hexdigest()) | 224 | expect_c = six.text_type(hashlib.md5(image_data).hexdigest()) |
238 | expect_h = six.text_type(hashlib.sha512(image_data).hexdigest()) | 225 | expect_h = six.text_type(hashlib.sha512(image_data).hexdigest()) |
239 | _verify_image_hashes_and_status(checksum=expect_c, | 226 | func_utils.verify_image_hashes_and_status(self, |
240 | os_hash_value=expect_h, | 227 | image_id, |
241 | status='active') | 228 | checksum=expect_c, |
229 | os_hash_value=expect_h, | ||
230 | status='active') | ||
242 | 231 | ||
243 | # Ensure the size is updated to reflect the data uploaded | 232 | # Ensure the size is updated to reflect the data uploaded |
244 | path = self._url('/v2/images/%s' % image_id) | 233 | path = self._url('/v2/images/%s' % image_id) |
@@ -341,22 +330,10 @@ class TestImages(functional.FunctionalTest): | |||
341 | self.assertEqual(1, len(images)) | 330 | self.assertEqual(1, len(images)) |
342 | self.assertEqual(image_id, images[0]['id']) | 331 | self.assertEqual(image_id, images[0]['id']) |
343 | 332 | ||
344 | def _verify_image_hashes_and_status( | ||
345 | checksum=None, os_hash_value=None, status=None): | ||
346 | path = self._url('/v2/images/%s' % image_id) | ||
347 | response = requests.get(path, headers=self._headers()) | ||
348 | self.assertEqual(http.OK, response.status_code) | ||
349 | image = jsonutils.loads(response.text) | ||
350 | self.assertEqual(checksum, image['checksum']) | ||
351 | if os_hash_value: | ||
352 | # make sure we're using the hashing_algorithm we expect | ||
353 | self.assertEqual(six.text_type('sha512'), | ||
354 | image['os_hash_algo']) | ||
355 | self.assertEqual(os_hash_value, image['os_hash_value']) | ||
356 | self.assertEqual(status, image['status']) | ||
357 | |||
358 | # Verify image is in queued state and hashes are None | 333 | # Verify image is in queued state and hashes are None |
359 | _verify_image_hashes_and_status(status='queued') | 334 | func_utils.verify_image_hashes_and_status(self, |
335 | image_id, | ||
336 | status='queued') | ||
360 | 337 | ||
361 | # Import image to store | 338 | # Import image to store |
362 | path = self._url('/v2/images/%s/import' % image_id) | 339 | path = self._url('/v2/images/%s/import' % image_id) |
@@ -386,9 +363,11 @@ class TestImages(functional.FunctionalTest): | |||
386 | with requests.get(image_data_uri) as r: | 363 | with requests.get(image_data_uri) as r: |
387 | expect_c = six.text_type(hashlib.md5(r.content).hexdigest()) | 364 | expect_c = six.text_type(hashlib.md5(r.content).hexdigest()) |
388 | expect_h = six.text_type(hashlib.sha512(r.content).hexdigest()) | 365 | expect_h = six.text_type(hashlib.sha512(r.content).hexdigest()) |
389 | _verify_image_hashes_and_status(checksum=expect_c, | 366 | func_utils.verify_image_hashes_and_status(self, |
390 | os_hash_value=expect_h, | 367 | image_id, |
391 | status='active') | 368 | checksum=expect_c, |
369 | os_hash_value=expect_h, | ||
370 | status='active') | ||
392 | 371 | ||
393 | # Deleting image should work | 372 | # Deleting image should work |
394 | path = self._url('/v2/images/%s' % image_id) | 373 | path = self._url('/v2/images/%s' % image_id) |
@@ -748,18 +727,6 @@ class TestImages(functional.FunctionalTest): | |||
748 | response = requests.get(path, headers=headers) | 727 | response = requests.get(path, headers=headers) |
749 | self.assertEqual(http.NO_CONTENT, response.status_code) | 728 | self.assertEqual(http.NO_CONTENT, response.status_code) |
750 | 729 | ||
751 | def _verify_image_hashes_and_status(checksum, os_hash_value, status): | ||
752 | # hashes should be populated and status should be active | ||
753 | path = self._url('/v2/images/%s' % image_id) | ||
754 | response = requests.get(path, headers=self._headers()) | ||
755 | self.assertEqual(http.OK, response.status_code) | ||
756 | image = jsonutils.loads(response.text) | ||
757 | self.assertEqual(checksum, image['checksum']) | ||
758 | # make sure we're using the default algo | ||
759 | self.assertEqual(six.text_type('sha512'), image['os_hash_algo']) | ||
760 | self.assertEqual(os_hash_value, image['os_hash_value']) | ||
761 | self.assertEqual(status, image['status']) | ||
762 | |||
763 | # Upload some image data | 730 | # Upload some image data |
764 | path = self._url('/v2/images/%s/file' % image_id) | 731 | path = self._url('/v2/images/%s/file' % image_id) |
765 | headers = self._headers({'Content-Type': 'application/octet-stream'}) | 732 | headers = self._headers({'Content-Type': 'application/octet-stream'}) |
@@ -769,7 +736,8 @@ class TestImages(functional.FunctionalTest): | |||
769 | 736 | ||
770 | expect_c = six.text_type(hashlib.md5(image_data).hexdigest()) | 737 | expect_c = six.text_type(hashlib.md5(image_data).hexdigest()) |
771 | expect_h = six.text_type(hashlib.sha512(image_data).hexdigest()) | 738 | expect_h = six.text_type(hashlib.sha512(image_data).hexdigest()) |
772 | _verify_image_hashes_and_status(expect_c, expect_h, 'active') | 739 | func_utils.verify_image_hashes_and_status(self, image_id, expect_c, |
740 | expect_h, 'active') | ||
773 | 741 | ||
774 | # `disk_format` and `container_format` cannot | 742 | # `disk_format` and `container_format` cannot |
775 | # be replaced when the image is active. | 743 | # be replaced when the image is active. |
@@ -797,7 +765,8 @@ class TestImages(functional.FunctionalTest): | |||
797 | headers = self._headers({'Content-Type': 'application/octet-stream'}) | 765 | headers = self._headers({'Content-Type': 'application/octet-stream'}) |
798 | response = requests.put(path, headers=headers, data='XXX') | 766 | response = requests.put(path, headers=headers, data='XXX') |
799 | self.assertEqual(http.CONFLICT, response.status_code) | 767 | self.assertEqual(http.CONFLICT, response.status_code) |
800 | _verify_image_hashes_and_status(expect_c, expect_h, 'active') | 768 | func_utils.verify_image_hashes_and_status(self, image_id, expect_c, |
769 | expect_h, 'active') | ||
801 | 770 | ||
802 | # Ensure the size is updated to reflect the data uploaded | 771 | # Ensure the size is updated to reflect the data uploaded |
803 | path = self._url('/v2/images/%s' % image_id) | 772 | path = self._url('/v2/images/%s' % image_id) |
@@ -1100,33 +1069,32 @@ class TestImages(functional.FunctionalTest): | |||
1100 | response = requests.get(path, headers=self._headers()) | 1069 | response = requests.get(path, headers=self._headers()) |
1101 | self.assertEqual(http.BAD_REQUEST, response.status_code) | 1070 | self.assertEqual(http.BAD_REQUEST, response.status_code) |
1102 | 1071 | ||
1103 | def _verify_image_checksum_and_status(checksum, status): | ||
1104 | # Checksum should be populated and status should be active | ||
1105 | path = self._url('/v2/images/%s' % image_id) | ||
1106 | response = requests.get(path, headers=self._headers()) | ||
1107 | self.assertEqual(http.OK, response.status_code) | ||
1108 | image = jsonutils.loads(response.text) | ||
1109 | self.assertEqual(checksum, image['checksum']) | ||
1110 | self.assertEqual(status, image['status']) | ||
1111 | |||
1112 | # Upload some image data to image-1 | 1072 | # Upload some image data to image-1 |
1113 | path = self._url('/v2/images/%s/file' % image_id) | 1073 | path = self._url('/v2/images/%s/file' % image_id) |
1114 | headers = self._headers({'Content-Type': 'application/octet-stream'}) | 1074 | headers = self._headers({'Content-Type': 'application/octet-stream'}) |
1115 | response = requests.put(path, headers=headers, data='ZZZZZ') | 1075 | image_data = b'ZZZZZ' |
1076 | response = requests.put(path, headers=headers, data=image_data) | ||
1116 | self.assertEqual(http.NO_CONTENT, response.status_code) | 1077 | self.assertEqual(http.NO_CONTENT, response.status_code) |
1117 | 1078 | expect_c = six.text_type(hashlib.md5(image_data).hexdigest()) | |
1118 | expected_checksum = '8f113e38d28a79a5a451b16048cc2b72' | 1079 | expect_h = six.text_type(hashlib.sha512(image_data).hexdigest()) |
1119 | _verify_image_checksum_and_status(expected_checksum, 'active') | 1080 | func_utils.verify_image_hashes_and_status(self, |
1120 | 1081 | image_id, | |
1082 | expect_c, | ||
1083 | expect_h, | ||
1084 | status='active') | ||
1121 | # Upload some image data to image-2 | 1085 | # Upload some image data to image-2 |
1122 | path = self._url('/v2/images/%s/file' % image2_id) | 1086 | path = self._url('/v2/images/%s/file' % image2_id) |
1123 | headers = self._headers({'Content-Type': 'application/octet-stream'}) | 1087 | headers = self._headers({'Content-Type': 'application/octet-stream'}) |
1124 | response = requests.put(path, headers=headers, data='ZZZZZ') | 1088 | image_data = b'WWWWW' |
1089 | response = requests.put(path, headers=headers, data=image_data) | ||
1125 | self.assertEqual(http.NO_CONTENT, response.status_code) | 1090 | self.assertEqual(http.NO_CONTENT, response.status_code) |
1126 | 1091 | expect_c = six.text_type(hashlib.md5(image_data).hexdigest()) | |
1127 | expected_checksum = '8f113e38d28a79a5a451b16048cc2b72' | 1092 | expect_h = six.text_type(hashlib.sha512(image_data).hexdigest()) |
1128 | _verify_image_checksum_and_status(expected_checksum, 'active') | 1093 | func_utils.verify_image_hashes_and_status(self, |
1129 | 1094 | image2_id, | |
1095 | expect_c, | ||
1096 | expect_h, | ||
1097 | status='active') | ||
1130 | # Hide image-1 | 1098 | # Hide image-1 |
1131 | path = self._url('/v2/images/%s' % image_id) | 1099 | path = self._url('/v2/images/%s' % image_id) |
1132 | media_type = 'application/openstack-images-v2.1-json-patch' | 1100 | media_type = 'application/openstack-images-v2.1-json-patch' |
@@ -4601,23 +4569,16 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
4601 | self.assertEqual(1, len(images)) | 4569 | self.assertEqual(1, len(images)) |
4602 | self.assertEqual(image_id, images[0]['id']) | 4570 | self.assertEqual(image_id, images[0]['id']) |
4603 | 4571 | ||
4604 | def _verify_image_checksum_and_status(checksum=None, status=None): | ||
4605 | # Checksum should be populated and status should be active | ||
4606 | path = self._url('/v2/images/%s' % image_id) | ||
4607 | response = requests.get(path, headers=self._headers()) | ||
4608 | self.assertEqual(http.OK, response.status_code) | ||
4609 | image = jsonutils.loads(response.text) | ||
4610 | self.assertEqual(checksum, image['checksum']) | ||
4611 | self.assertEqual(status, image['status']) | ||
4612 | |||
4613 | # Upload some image data to staging area | 4572 | # Upload some image data to staging area |
4573 | image_data = b'QQQQQ' | ||
4614 | path = self._url('/v2/images/%s/stage' % image_id) | 4574 | path = self._url('/v2/images/%s/stage' % image_id) |
4615 | headers = self._headers({'Content-Type': 'application/octet-stream'}) | 4575 | headers = self._headers({'Content-Type': 'application/octet-stream'}) |
4616 | response = requests.put(path, headers=headers, data='ZZZZZ') | 4576 | response = requests.put(path, headers=headers, data=image_data) |
4617 | self.assertEqual(http.NO_CONTENT, response.status_code) | 4577 | self.assertEqual(http.NO_CONTENT, response.status_code) |
4618 | 4578 | ||
4619 | # Verify image is in uploading state and checksum is None | 4579 | # Verify image is in uploading state and checksum is None |
4620 | _verify_image_checksum_and_status(status='uploading') | 4580 | func_utils.verify_image_hashes_and_status(self, image_id, |
4581 | status='uploading') | ||
4621 | 4582 | ||
4622 | # Import image to store | 4583 | # Import image to store |
4623 | path = self._url('/v2/images/%s/import' % image_id) | 4584 | path = self._url('/v2/images/%s/import' % image_id) |
@@ -4640,15 +4601,20 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
4640 | status='active', | 4601 | status='active', |
4641 | max_sec=2, | 4602 | max_sec=2, |
4642 | delay_sec=0.2) | 4603 | delay_sec=0.2) |
4643 | _verify_image_checksum_and_status( | 4604 | expect_c = six.text_type(hashlib.md5(image_data).hexdigest()) |
4644 | checksum='8f113e38d28a79a5a451b16048cc2b72', | 4605 | expect_h = six.text_type(hashlib.sha512(image_data).hexdigest()) |
4645 | status='active') | 4606 | func_utils.verify_image_hashes_and_status(self, |
4607 | image_id, | ||
4608 | checksum=expect_c, | ||
4609 | os_hash_value=expect_h, | ||
4610 | status='active') | ||
4646 | 4611 | ||
4647 | # Ensure the size is updated to reflect the data uploaded | 4612 | # Ensure the size is updated to reflect the data uploaded |
4648 | path = self._url('/v2/images/%s' % image_id) | 4613 | path = self._url('/v2/images/%s' % image_id) |
4649 | response = requests.get(path, headers=self._headers()) | 4614 | response = requests.get(path, headers=self._headers()) |
4650 | self.assertEqual(http.OK, response.status_code) | 4615 | self.assertEqual(http.OK, response.status_code) |
4651 | self.assertEqual(5, jsonutils.loads(response.text)['size']) | 4616 | self.assertEqual(len(image_data), |
4617 | jsonutils.loads(response.text)['size']) | ||
4652 | 4618 | ||
4653 | # Ensure image is created in default backend | 4619 | # Ensure image is created in default backend |
4654 | self.assertIn('file1', jsonutils.loads(response.text)['stores']) | 4620 | self.assertIn('file1', jsonutils.loads(response.text)['stores']) |
@@ -4763,23 +4729,16 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
4763 | self.assertEqual(1, len(images)) | 4729 | self.assertEqual(1, len(images)) |
4764 | self.assertEqual(image_id, images[0]['id']) | 4730 | self.assertEqual(image_id, images[0]['id']) |
4765 | 4731 | ||
4766 | def _verify_image_checksum_and_status(checksum=None, status=None): | ||
4767 | # Checksum should be populated and status should be active | ||
4768 | path = self._url('/v2/images/%s' % image_id) | ||
4769 | response = requests.get(path, headers=self._headers()) | ||
4770 | self.assertEqual(http.OK, response.status_code) | ||
4771 | image = jsonutils.loads(response.text) | ||
4772 | self.assertEqual(checksum, image['checksum']) | ||
4773 | self.assertEqual(status, image['status']) | ||
4774 | |||
4775 | # Upload some image data to staging area | 4732 | # Upload some image data to staging area |
4733 | image_data = b'GLANCE IS DEAD SEXY' | ||
4776 | path = self._url('/v2/images/%s/stage' % image_id) | 4734 | path = self._url('/v2/images/%s/stage' % image_id) |
4777 | headers = self._headers({'Content-Type': 'application/octet-stream'}) | 4735 | headers = self._headers({'Content-Type': 'application/octet-stream'}) |
4778 | response = requests.put(path, headers=headers, data='ZZZZZ') | 4736 | response = requests.put(path, headers=headers, data=image_data) |
4779 | self.assertEqual(http.NO_CONTENT, response.status_code) | 4737 | self.assertEqual(http.NO_CONTENT, response.status_code) |
4780 | 4738 | ||
4781 | # Verify image is in uploading state and checksum is None | 4739 | # Verify image is in uploading state and checksum is None |
4782 | _verify_image_checksum_and_status(status='uploading') | 4740 | func_utils.verify_image_hashes_and_status(self, image_id, |
4741 | status='uploading') | ||
4783 | 4742 | ||
4784 | # Import image to file2 store (other than default backend) | 4743 | # Import image to file2 store (other than default backend) |
4785 | path = self._url('/v2/images/%s/import' % image_id) | 4744 | path = self._url('/v2/images/%s/import' % image_id) |
@@ -4803,15 +4762,20 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
4803 | status='active', | 4762 | status='active', |
4804 | max_sec=2, | 4763 | max_sec=2, |
4805 | delay_sec=0.2) | 4764 | delay_sec=0.2) |
4806 | _verify_image_checksum_and_status( | 4765 | expect_c = six.text_type(hashlib.md5(image_data).hexdigest()) |
4807 | checksum='8f113e38d28a79a5a451b16048cc2b72', | 4766 | expect_h = six.text_type(hashlib.sha512(image_data).hexdigest()) |
4808 | status='active') | 4767 | func_utils.verify_image_hashes_and_status(self, |
4768 | image_id, | ||
4769 | checksum=expect_c, | ||
4770 | os_hash_value=expect_h, | ||
4771 | status='active') | ||
4809 | 4772 | ||
4810 | # Ensure the size is updated to reflect the data uploaded | 4773 | # Ensure the size is updated to reflect the data uploaded |
4811 | path = self._url('/v2/images/%s' % image_id) | 4774 | path = self._url('/v2/images/%s' % image_id) |
4812 | response = requests.get(path, headers=self._headers()) | 4775 | response = requests.get(path, headers=self._headers()) |
4813 | self.assertEqual(http.OK, response.status_code) | 4776 | self.assertEqual(http.OK, response.status_code) |
4814 | self.assertEqual(5, jsonutils.loads(response.text)['size']) | 4777 | self.assertEqual(len(image_data), |
4778 | jsonutils.loads(response.text)['size']) | ||
4815 | 4779 | ||
4816 | # Ensure image is created in different backend | 4780 | # Ensure image is created in different backend |
4817 | self.assertIn('file2', jsonutils.loads(response.text)['stores']) | 4781 | self.assertIn('file2', jsonutils.loads(response.text)['stores']) |
@@ -4927,17 +4891,9 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
4927 | self.assertEqual(1, len(images)) | 4891 | self.assertEqual(1, len(images)) |
4928 | self.assertEqual(image_id, images[0]['id']) | 4892 | self.assertEqual(image_id, images[0]['id']) |
4929 | 4893 | ||
4930 | def _verify_image_checksum_and_status(checksum=None, status=None): | ||
4931 | # Checksum should be populated and status should be active | ||
4932 | path = self._url('/v2/images/%s' % image_id) | ||
4933 | response = requests.get(path, headers=self._headers()) | ||
4934 | self.assertEqual(http.OK, response.status_code) | ||
4935 | image = jsonutils.loads(response.text) | ||
4936 | self.assertEqual(checksum, image['checksum']) | ||
4937 | self.assertEqual(status, image['status']) | ||
4938 | |||
4939 | # Verify image is in queued state and checksum is None | 4894 | # Verify image is in queued state and checksum is None |
4940 | _verify_image_checksum_and_status(status='queued') | 4895 | func_utils.verify_image_hashes_and_status(self, image_id, |
4896 | status='queued') | ||
4941 | 4897 | ||
4942 | # Import image to store | 4898 | # Import image to store |
4943 | path = self._url('/v2/images/%s/import' % image_id) | 4899 | path = self._url('/v2/images/%s/import' % image_id) |
@@ -4945,10 +4901,11 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
4945 | 'content-type': 'application/json', | 4901 | 'content-type': 'application/json', |
4946 | 'X-Roles': 'admin', | 4902 | 'X-Roles': 'admin', |
4947 | }) | 4903 | }) |
4904 | image_data_uri = ('https://www.openstack.org/assets/openstack-logo/' | ||
4905 | '2016R/OpenStack-Logo-Horizontal.eps.zip') | ||
4948 | data = jsonutils.dumps({'method': { | 4906 | data = jsonutils.dumps({'method': { |
4949 | 'name': 'web-download', | 4907 | 'name': 'web-download', |
4950 | 'uri': 'https://www.openstack.org/assets/openstack-logo/' | 4908 | 'uri': image_data_uri |
4951 | '2016R/OpenStack-Logo-Horizontal.eps.zip' | ||
4952 | }}) | 4909 | }}) |
4953 | response = requests.post(path, headers=headers, data=data) | 4910 | response = requests.post(path, headers=headers, data=data) |
4954 | self.assertEqual(http.ACCEPTED, response.status_code) | 4911 | self.assertEqual(http.ACCEPTED, response.status_code) |
@@ -4963,10 +4920,14 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
4963 | max_sec=20, | 4920 | max_sec=20, |
4964 | delay_sec=0.2, | 4921 | delay_sec=0.2, |
4965 | start_delay_sec=1) | 4922 | start_delay_sec=1) |
4966 | _verify_image_checksum_and_status( | 4923 | with requests.get(image_data_uri) as r: |
4967 | checksum='bcd65f8922f61a9e6a20572ad7aa2bdd', | 4924 | expect_c = six.text_type(hashlib.md5(r.content).hexdigest()) |
4968 | status='active') | 4925 | expect_h = six.text_type(hashlib.sha512(r.content).hexdigest()) |
4969 | 4926 | func_utils.verify_image_hashes_and_status(self, | |
4927 | image_id, | ||
4928 | checksum=expect_c, | ||
4929 | os_hash_value=expect_h, | ||
4930 | status='active') | ||
4970 | # Ensure image is created in default backend | 4931 | # Ensure image is created in default backend |
4971 | path = self._url('/v2/images/%s' % image_id) | 4932 | path = self._url('/v2/images/%s' % image_id) |
4972 | response = requests.get(path, headers=self._headers()) | 4933 | response = requests.get(path, headers=self._headers()) |
@@ -5084,18 +5045,9 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
5084 | self.assertEqual(1, len(images)) | 5045 | self.assertEqual(1, len(images)) |
5085 | self.assertEqual(image_id, images[0]['id']) | 5046 | self.assertEqual(image_id, images[0]['id']) |
5086 | 5047 | ||
5087 | def _verify_image_checksum_and_status(checksum=None, status=None): | ||
5088 | # Checksum should be populated and status should be active | ||
5089 | path = self._url('/v2/images/%s' % image_id) | ||
5090 | response = requests.get(path, headers=self._headers()) | ||
5091 | self.assertEqual(http.OK, response.status_code) | ||
5092 | image = jsonutils.loads(response.text) | ||
5093 | self.assertEqual(checksum, image['checksum']) | ||
5094 | self.assertEqual(status, image['status']) | ||
5095 | |||
5096 | # Verify image is in queued state and checksum is None | 5048 | # Verify image is in queued state and checksum is None |
5097 | _verify_image_checksum_and_status(status='queued') | 5049 | func_utils.verify_image_hashes_and_status(self, image_id, |
5098 | 5050 | status='queued') | |
5099 | # Import image to store | 5051 | # Import image to store |
5100 | path = self._url('/v2/images/%s/import' % image_id) | 5052 | path = self._url('/v2/images/%s/import' % image_id) |
5101 | headers = self._headers({ | 5053 | headers = self._headers({ |
@@ -5103,10 +5055,11 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
5103 | 'X-Roles': 'admin', | 5055 | 'X-Roles': 'admin', |
5104 | 'X-Image-Meta-Store': 'file2' | 5056 | 'X-Image-Meta-Store': 'file2' |
5105 | }) | 5057 | }) |
5058 | image_data_uri = ('https://www.openstack.org/assets/openstack-logo/' | ||
5059 | '2016R/OpenStack-Logo-Horizontal.eps.zip') | ||
5106 | data = jsonutils.dumps({'method': { | 5060 | data = jsonutils.dumps({'method': { |
5107 | 'name': 'web-download', | 5061 | 'name': 'web-download', |
5108 | 'uri': 'https://www.openstack.org/assets/openstack-logo/' | 5062 | 'uri': image_data_uri |
5109 | '2016R/OpenStack-Logo-Horizontal.eps.zip' | ||
5110 | }}) | 5063 | }}) |
5111 | response = requests.post(path, headers=headers, data=data) | 5064 | response = requests.post(path, headers=headers, data=data) |
5112 | self.assertEqual(http.ACCEPTED, response.status_code) | 5065 | self.assertEqual(http.ACCEPTED, response.status_code) |
@@ -5121,10 +5074,14 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
5121 | max_sec=20, | 5074 | max_sec=20, |
5122 | delay_sec=0.2, | 5075 | delay_sec=0.2, |
5123 | start_delay_sec=1) | 5076 | start_delay_sec=1) |
5124 | _verify_image_checksum_and_status( | 5077 | with requests.get(image_data_uri) as r: |
5125 | checksum='bcd65f8922f61a9e6a20572ad7aa2bdd', | 5078 | expect_c = six.text_type(hashlib.md5(r.content).hexdigest()) |
5126 | status='active') | 5079 | expect_h = six.text_type(hashlib.sha512(r.content).hexdigest()) |
5127 | 5080 | func_utils.verify_image_hashes_and_status(self, | |
5081 | image_id, | ||
5082 | checksum=expect_c, | ||
5083 | os_hash_value=expect_h, | ||
5084 | status='active') | ||
5128 | # Ensure image is created in different backend | 5085 | # Ensure image is created in different backend |
5129 | path = self._url('/v2/images/%s' % image_id) | 5086 | path = self._url('/v2/images/%s' % image_id) |
5130 | response = requests.get(path, headers=self._headers()) | 5087 | response = requests.get(path, headers=self._headers()) |
@@ -5243,23 +5200,20 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
5243 | response = requests.get(path, headers=headers) | 5200 | response = requests.get(path, headers=headers) |
5244 | self.assertEqual(http.NO_CONTENT, response.status_code) | 5201 | self.assertEqual(http.NO_CONTENT, response.status_code) |
5245 | 5202 | ||
5246 | def _verify_image_checksum_and_status(checksum, status): | ||
5247 | # Checksum should be populated and status should be active | ||
5248 | path = self._url('/v2/images/%s' % image_id) | ||
5249 | response = requests.get(path, headers=self._headers()) | ||
5250 | self.assertEqual(http.OK, response.status_code) | ||
5251 | image = jsonutils.loads(response.text) | ||
5252 | self.assertEqual(checksum, image['checksum']) | ||
5253 | self.assertEqual(status, image['status']) | ||
5254 | |||
5255 | # Upload some image data | 5203 | # Upload some image data |
5204 | image_data = b'OpenStack Rules, Other Clouds Drool' | ||
5256 | path = self._url('/v2/images/%s/file' % image_id) | 5205 | path = self._url('/v2/images/%s/file' % image_id) |
5257 | headers = self._headers({'Content-Type': 'application/octet-stream'}) | 5206 | headers = self._headers({'Content-Type': 'application/octet-stream'}) |
5258 | response = requests.put(path, headers=headers, data='ZZZZZ') | 5207 | response = requests.put(path, headers=headers, data=image_data) |
5259 | self.assertEqual(http.NO_CONTENT, response.status_code) | 5208 | self.assertEqual(http.NO_CONTENT, response.status_code) |
5260 | 5209 | ||
5261 | expected_checksum = '8f113e38d28a79a5a451b16048cc2b72' | 5210 | expect_c = six.text_type(hashlib.md5(image_data).hexdigest()) |
5262 | _verify_image_checksum_and_status(expected_checksum, 'active') | 5211 | expect_h = six.text_type(hashlib.sha512(image_data).hexdigest()) |
5212 | func_utils.verify_image_hashes_and_status(self, | ||
5213 | image_id, | ||
5214 | checksum=expect_c, | ||
5215 | os_hash_value=expect_h, | ||
5216 | status='active') | ||
5263 | 5217 | ||
5264 | # Ensure image is created in default backend | 5218 | # Ensure image is created in default backend |
5265 | path = self._url('/v2/images/%s' % image_id) | 5219 | path = self._url('/v2/images/%s' % image_id) |
@@ -5271,14 +5225,15 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
5271 | path = self._url('/v2/images/%s/file' % image_id) | 5225 | path = self._url('/v2/images/%s/file' % image_id) |
5272 | response = requests.get(path, headers=self._headers()) | 5226 | response = requests.get(path, headers=self._headers()) |
5273 | self.assertEqual(http.OK, response.status_code) | 5227 | self.assertEqual(http.OK, response.status_code) |
5274 | self.assertEqual(expected_checksum, response.headers['Content-MD5']) | 5228 | self.assertEqual(expect_c, response.headers['Content-MD5']) |
5275 | self.assertEqual('ZZZZZ', response.text) | 5229 | self.assertEqual(image_data.decode('utf-8'), response.text) |
5276 | 5230 | ||
5277 | # Ensure the size is updated to reflect the data uploaded | 5231 | # Ensure the size is updated to reflect the data uploaded |
5278 | path = self._url('/v2/images/%s' % image_id) | 5232 | path = self._url('/v2/images/%s' % image_id) |
5279 | response = requests.get(path, headers=self._headers()) | 5233 | response = requests.get(path, headers=self._headers()) |
5280 | self.assertEqual(http.OK, response.status_code) | 5234 | self.assertEqual(http.OK, response.status_code) |
5281 | self.assertEqual(5, jsonutils.loads(response.text)['size']) | 5235 | self.assertEqual(len(image_data), |
5236 | jsonutils.loads(response.text)['size']) | ||
5282 | 5237 | ||
5283 | # Unprotect image for deletion | 5238 | # Unprotect image for deletion |
5284 | path = self._url('/v2/images/%s' % image_id) | 5239 | path = self._url('/v2/images/%s' % image_id) |
@@ -5413,26 +5368,23 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
5413 | response = requests.get(path, headers=headers) | 5368 | response = requests.get(path, headers=headers) |
5414 | self.assertEqual(http.NO_CONTENT, response.status_code) | 5369 | self.assertEqual(http.NO_CONTENT, response.status_code) |
5415 | 5370 | ||
5416 | def _verify_image_checksum_and_status(checksum, status): | ||
5417 | # Checksum should be populated and status should be active | ||
5418 | path = self._url('/v2/images/%s' % image_id) | ||
5419 | response = requests.get(path, headers=self._headers()) | ||
5420 | self.assertEqual(http.OK, response.status_code) | ||
5421 | image = jsonutils.loads(response.text) | ||
5422 | self.assertEqual(checksum, image['checksum']) | ||
5423 | self.assertEqual(status, image['status']) | ||
5424 | |||
5425 | # Upload some image data | 5371 | # Upload some image data |
5372 | image_data = b'just a passing glance' | ||
5426 | path = self._url('/v2/images/%s/file' % image_id) | 5373 | path = self._url('/v2/images/%s/file' % image_id) |
5427 | headers = self._headers({ | 5374 | headers = self._headers({ |
5428 | 'Content-Type': 'application/octet-stream', | 5375 | 'Content-Type': 'application/octet-stream', |
5429 | 'X-Image-Meta-Store': 'file2' | 5376 | 'X-Image-Meta-Store': 'file2' |
5430 | }) | 5377 | }) |
5431 | response = requests.put(path, headers=headers, data='ZZZZZ') | 5378 | response = requests.put(path, headers=headers, data=image_data) |
5432 | self.assertEqual(http.NO_CONTENT, response.status_code) | 5379 | self.assertEqual(http.NO_CONTENT, response.status_code) |
5433 | 5380 | ||
5434 | expected_checksum = '8f113e38d28a79a5a451b16048cc2b72' | 5381 | expect_c = six.text_type(hashlib.md5(image_data).hexdigest()) |
5435 | _verify_image_checksum_and_status(expected_checksum, 'active') | 5382 | expect_h = six.text_type(hashlib.sha512(image_data).hexdigest()) |
5383 | func_utils.verify_image_hashes_and_status(self, | ||
5384 | image_id, | ||
5385 | checksum=expect_c, | ||
5386 | os_hash_value=expect_h, | ||
5387 | status='active') | ||
5436 | 5388 | ||
5437 | # Ensure image is created in different backend | 5389 | # Ensure image is created in different backend |
5438 | path = self._url('/v2/images/%s' % image_id) | 5390 | path = self._url('/v2/images/%s' % image_id) |
@@ -5444,14 +5396,15 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest): | |||
5444 | path = self._url('/v2/images/%s/file' % image_id) | 5396 | path = self._url('/v2/images/%s/file' % image_id) |
5445 | response = requests.get(path, headers=self._headers()) | 5397 | response = requests.get(path, headers=self._headers()) |
5446 | self.assertEqual(http.OK, response.status_code) | 5398 | self.assertEqual(http.OK, response.status_code) |
5447 | self.assertEqual(expected_checksum, response.headers['Content-MD5']) | 5399 | self.assertEqual(expect_c, response.headers['Content-MD5']) |
5448 | self.assertEqual('ZZZZZ', response.text) | 5400 | self.assertEqual(image_data.decode('utf-8'), response.text) |
5449 | 5401 | ||
5450 | # Ensure the size is updated to reflect the data uploaded | 5402 | # Ensure the size is updated to reflect the data uploaded |
5451 | path = self._url('/v2/images/%s' % image_id) | 5403 | path = self._url('/v2/images/%s' % image_id) |
5452 | response = requests.get(path, headers=self._headers()) | 5404 | response = requests.get(path, headers=self._headers()) |
5453 | self.assertEqual(http.OK, response.status_code) | 5405 | self.assertEqual(http.OK, response.status_code) |
5454 | self.assertEqual(5, jsonutils.loads(response.text)['size']) | 5406 | self.assertEqual(len(image_data), |
5407 | jsonutils.loads(response.text)['size']) | ||
5455 | 5408 | ||
5456 | # Unprotect image for deletion | 5409 | # Unprotect image for deletion |
5457 | path = self._url('/v2/images/%s' % image_id) | 5410 | path = self._url('/v2/images/%s' % image_id) |