Merge "Accepts option for conv flags in dd command"
This commit is contained in:
commit
66b098ee6d
|
@ -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})
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue