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
This commit is contained in:
Dan Smith 2021-04-26 14:51:43 -07:00
parent a1e46cca6e
commit 154ef3fe94
4 changed files with 15 additions and 6 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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,

View File

@ -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()