From 154ef3fe94fb71712e9da12c8eb53b04c8b2efa4 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Mon, 26 Apr 2021 14:51:43 -0700 Subject: [PATCH] Update image.size after conversion When we convert an image to a specified format during import, we update the disk_format to match. At that point, we also know the (new) image.size, so we should set it. This is somewhat related to setting image size on stage, in that once it is set we will validate that it does not change in later steps. Since this one comes between stage and the actual store upload, this patch makes conversion set it and confirms that the later steps are happy with that. A later patch sets it during stage, confirming that we can change it here during conversion when we are changing the actual image file itself. Related to blueprint glance-unified-quotas Change-Id: I795c52f606f85955e39efc29b75f2941be1264b4 --- glance/async_/flows/api_image_import.py | 2 +- glance/async_/flows/plugins/image_conversion.py | 6 +++++- .../unit/async_/flows/plugins/test_image_conversion.py | 9 ++++++--- glance/tests/unit/async_/flows/test_api_image_import.py | 4 +++- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/glance/async_/flows/api_image_import.py b/glance/async_/flows/api_image_import.py index 4c543162a8..49e523c8ec 100644 --- a/glance/async_/flows/api_image_import.py +++ b/glance/async_/flows/api_image_import.py @@ -309,7 +309,7 @@ class _ImportActions(object): ones is present in attrs. """ allowed = ['status', 'disk_format', 'container_format', - 'virtual_size'] + 'virtual_size', 'size'] for attr, value in attrs.items(): if attr not in allowed: raise AttributeError('Setting %s is not allowed' % attr) diff --git a/glance/async_/flows/plugins/image_conversion.py b/glance/async_/flows/plugins/image_conversion.py index ec92a31537..32c7b7fe09 100644 --- a/glance/async_/flows/plugins/image_conversion.py +++ b/glance/async_/flows/plugins/image_conversion.py @@ -25,7 +25,7 @@ from taskflow.patterns import linear_flow as lf from taskflow import task from glance.async_ import utils -from glance.i18n import _ +from glance.i18n import _, _LI LOG = logging.getLogger(__name__) @@ -138,6 +138,10 @@ class _ConvertImage(task.Task): action.set_image_attribute(disk_format=target_format, container_format='bare') + new_size = os.stat(dest_path).st_size + action.set_image_attribute(size=new_size) + LOG.info(_LI('Updated image %s size=%i disk_format=%s'), + self.image_id, new_size, target_format) os.remove(src_path) diff --git a/glance/tests/unit/async_/flows/plugins/test_image_conversion.py b/glance/tests/unit/async_/flows/plugins/test_image_conversion.py index 9327748ddb..eaa84f43db 100644 --- a/glance/tests/unit/async_/flows/plugins/test_image_conversion.py +++ b/glance/tests/unit/async_/flows/plugins/test_image_conversion.py @@ -90,9 +90,11 @@ class TestConvertImageTask(test_utils.BaseTestCase): self.image_id, self.task.task_id) + @mock.patch.object(os, 'stat') @mock.patch.object(os, 'remove') - def test_image_convert_success(self, mock_os_remove): + def test_image_convert_success(self, mock_os_remove, mock_os_stat): mock_os_remove.return_value = None + mock_os_stat.return_value.st_size = 123 image_convert = image_conversion._ConvertImage(self.context, self.task.task_id, self.task_type, @@ -109,7 +111,7 @@ class TestConvertImageTask(test_utils.BaseTestCase): exc_mock.return_value = ("", None) with mock.patch.object(json, 'loads') as jloads_mock: jloads_mock.return_value = {'format': 'raw', - 'virtual-size': 123} + 'virtual-size': 456} image_convert.execute('file:///test/path.raw') # NOTE(hemanthm): Asserting that the source format is passed @@ -121,7 +123,8 @@ class TestConvertImageTask(test_utils.BaseTestCase): self.assertEqual('bare', image.container_format) self.assertEqual('qcow2', image.disk_format) - self.assertEqual(123, image.virtual_size) + self.assertEqual(456, image.virtual_size) + self.assertEqual(123, image.size) def _setup_image_convert_info_fail(self): image_convert = image_conversion._ConvertImage(self.context, diff --git a/glance/tests/unit/async_/flows/test_api_image_import.py b/glance/tests/unit/async_/flows/test_api_image_import.py index 5d88640333..5029c200fb 100644 --- a/glance/tests/unit/async_/flows/test_api_image_import.py +++ b/glance/tests/unit/async_/flows/test_api_image_import.py @@ -688,10 +688,12 @@ class TestImportActionWrapper(test_utils.BaseTestCase): wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1, TASK_ID1) with wrapper as action: - action.set_image_attribute(status='foo', virtual_size=123) + action.set_image_attribute(status='foo', virtual_size=123, + size=64) mock_repo.save.assert_called_once_with(mock_image, 'bar') self.assertEqual('foo', mock_image.status) self.assertEqual(123, mock_image.virtual_size) + self.assertEqual(64, mock_image.size) def test_set_image_attribute_disallowed(self): mock_repo = mock.MagicMock()