Merge "Accepts option for conv flags in dd command"

This commit is contained in:
Zuul 2018-09-21 11:15:15 +00:00 committed by Gerrit Code Review
commit 66b098ee6d
2 changed files with 54 additions and 12 deletions

View File

@ -313,9 +313,15 @@ def is_block_device(dev):
raise exception.InstanceDeployFailure(msg)
def dd(src, dst):
def dd(src, dst, conv_flags=None):
"""Execute dd from src to dst."""
utils.dd(src, dst, 'bs=%s' % CONF.disk_utils.dd_block_size, 'oflag=direct')
if conv_flags:
extra_args = ['conv=%s' % conv_flags]
else:
extra_args = []
utils.dd(src, dst, 'bs=%s' % CONF.disk_utils.dd_block_size, 'oflag=direct',
*extra_args)
def qemu_img_info(path):
@ -335,10 +341,10 @@ def convert_image(source, dest, out_format, run_as_root=False):
utils.execute(*cmd, run_as_root=run_as_root, prlimit=QEMU_IMG_LIMITS)
def populate_image(src, dst):
def populate_image(src, dst, conv_flags=None):
data = qemu_img_info(src)
if data.file_format == 'raw':
dd(src, dst)
dd(src, dst, conv_flags=conv_flags)
else:
convert_image(src, dst, 'raw', True)
@ -485,7 +491,7 @@ def _get_configdrive(configdrive, node_uuid, tempdir=None):
def work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, ephemeral_format,
image_path, node_uuid, preserve_ephemeral=False,
configdrive=None, boot_option="netboot", boot_mode="bios",
tempdir=None, disk_label=None, cpu_arch=""):
tempdir=None, disk_label=None, cpu_arch="", conv_flags=None):
"""Create partitions and copy an image to the root partition.
:param dev: Path for the device to work on.
@ -513,6 +519,9 @@ def work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, ephemeral_format,
steps will be taken. This default should be used for x86_64. When
set to ppc64*, architecture specific steps are taken for booting a
partition image locally.
:param conv_flags: Flags that need to be sent to the dd command, to control
the conversion of the original file when copying to the host. It can
contain several options separated by commas.
:returns: a dictionary containing the following keys:
'root uuid': UUID of root partition
'efi system partition uuid': UUID of the uefi system partition
@ -575,7 +584,7 @@ def work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, ephemeral_format,
if configdrive_part:
# Copy the configdrive content to the configdrive partition
dd(configdrive_file, configdrive_part)
dd(configdrive_file, configdrive_part, conv_flags=conv_flags)
LOG.info("Configdrive for node %(node)s successfully copied "
"onto partition %(partition)s",
{'node': node_uuid, 'partition': configdrive_part})
@ -586,7 +595,7 @@ def work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, ephemeral_format,
if configdrive_file:
utils.unlink_without_raise(configdrive_file)
populate_image(image_path, root_part)
populate_image(image_path, root_part, conv_flags=conv_flags)
LOG.info("Image for %(node)s successfully populated",
{'node': node_uuid})

View File

@ -202,7 +202,8 @@ class WorkOnDiskTestCase(base.IronicLibTestCase):
@mock.patch.object(utils, 'mkfs', lambda fs, path, label=None: None)
@mock.patch.object(disk_utils, 'block_uuid', lambda p: 'uuid')
@mock.patch.object(disk_utils, 'populate_image', lambda *_: None)
@mock.patch.object(disk_utils, 'populate_image', lambda image_path,
root_path, conv_flags=None: None)
def test_gpt_disk_label(self):
ephemeral_part = '/dev/fake-part1'
swap_part = '/dev/fake-part2'
@ -220,7 +221,7 @@ class WorkOnDiskTestCase(base.IronicLibTestCase):
disk_utils.work_on_disk(self.dev, self.root_mb,
self.swap_mb, ephemeral_mb, ephemeral_format,
self.image_path, self.node_uuid,
disk_label='gpt')
disk_label='gpt', conv_flags=None)
self.assertEqual(self.mock_ibd.call_args_list, calls)
self.mock_mp.assert_called_once_with(self.dev, self.root_mb,
self.swap_mb, ephemeral_mb,
@ -263,7 +264,7 @@ class WorkOnDiskTestCase(base.IronicLibTestCase):
mock_mkfs.assert_called_once_with(fs='vfat', path=efi_part,
label='efi-part')
mock_populate_image.assert_called_once_with(self.image_path,
root_part)
root_part, conv_flags=None)
mock_block_uuid.assert_any_call(root_part)
mock_block_uuid.assert_any_call(efi_part)
@ -309,7 +310,7 @@ class WorkOnDiskTestCase(base.IronicLibTestCase):
self.mock_mp.return_value = {'PReP Boot partition': prep_part,
'root': root_part}
self.mock_ibd.return_value = True
self.mock_ibd.return_vaue = True
calls = [mock.call(root_part),
mock.call(prep_part)]
disk_utils.work_on_disk(self.dev, self.root_mb,
@ -328,6 +329,30 @@ class WorkOnDiskTestCase(base.IronicLibTestCase):
cpu_arch="ppc64le")
self.assertFalse(mock_mkfs.called)
@mock.patch.object(disk_utils, 'block_uuid', autospec=True)
@mock.patch.object(disk_utils, 'populate_image', autospec=True)
@mock.patch.object(utils, 'mkfs', autospec=True)
def test_convert_to_sparse(self, mock_mkfs, mock_populate_image,
mock_block_uuid):
ephemeral_part = '/dev/fake-part1'
swap_part = '/dev/fake-part2'
root_part = '/dev/fake-part3'
ephemeral_mb = 256
ephemeral_format = 'exttest'
self.mock_mp.return_value = {'ephemeral': ephemeral_part,
'swap': swap_part,
'root': root_part}
self.mock_ibd.return_value = True
disk_utils.work_on_disk(self.dev, self.root_mb,
self.swap_mb, ephemeral_mb, ephemeral_format,
self.image_path, self.node_uuid,
disk_label='gpt', conv_flags='sparse')
mock_populate_image.assert_called_once_with(self.image_path,
root_part,
conv_flags='sparse')
@mock.patch.object(utils, 'execute', autospec=True)
class MakePartitionsTestCase(base.IronicLibTestCase):
@ -612,7 +637,15 @@ class PopulateImageTestCase(base.IronicLibTestCase):
type(mock_qinfo.return_value).file_format = mock.PropertyMock(
return_value='raw')
disk_utils.populate_image('src', 'dst')
mock_dd.assert_called_once_with('src', 'dst')
mock_dd.assert_called_once_with('src', 'dst', conv_flags=None)
self.assertFalse(mock_cg.called)
def test_populate_raw_image_with_convert(self, mock_cg, mock_qinfo,
mock_dd):
type(mock_qinfo.return_value).file_format = mock.PropertyMock(
return_value='raw')
disk_utils.populate_image('src', 'dst', conv_flags='sparse')
mock_dd.assert_called_once_with('src', 'dst', conv_flags='sparse')
self.assertFalse(mock_cg.called)
def test_populate_qcow2_image(self, mock_cg, mock_qinfo, mock_dd):