Expose GPT partitioning fixing method

As suggested by TheJulia, the `_fix_gpt_structs` code
which is currently not accessible/callable from outside of ironic-lib
should be exposed so that other code like ironic-python-agent
can use it such as https://review.openstack.org/#/c/568524/

This patchset now exposes this code as `fix_gpt_structs`
(no leading underscore).

Change-Id: Icd824982d23966605fb179270bbf428cab23a41d
This commit is contained in:
Olivier Bourdon 2018-05-14 17:09:56 +02:00
parent 89fbae42ac
commit a809787783
2 changed files with 59 additions and 8 deletions

View File

@ -719,6 +719,28 @@ def _fix_gpt_structs(device, node_uuid):
raise exception.InstanceDeployFailure(msg)
def fix_gpt_partition(device, node_uuid):
"""Fix GPT partition
Fix GPT table information when image is written to a disk which
has a bigger extend (e.g. 30GB image written on a 60Gb physical disk).
:param device: The device path.
:param node_uuid: UUID of the Node.
:raises: InstanceDeployFailure if exception is caught.
"""
try:
disk_is_gpt_partitioned = _is_disk_gpt_partitioned(device, node_uuid)
if disk_is_gpt_partitioned:
_fix_gpt_structs(device, node_uuid)
except Exception as e:
msg = (_('Failed to fix GPT partition on disk %(disk)s '
'for node %(node)s. Error: %(error)s') %
{'disk': device, 'node': node_uuid, 'error': e})
LOG.error(msg)
raise exception.InstanceDeployFailure(msg)
def create_config_drive_partition(node_uuid, device, configdrive):
"""Create a partition for config drive
@ -751,6 +773,7 @@ def create_config_drive_partition(node_uuid, device, configdrive):
"device: %(dev)s for node %(node)s",
{'dev': device, 'size': confdrive_mb, 'node': node_uuid})
fix_gpt_partition(device, node_uuid)
if config_drive_part:
LOG.debug("Configdrive for node %(node)s exists at "
"%(part)s",
@ -759,7 +782,6 @@ def create_config_drive_partition(node_uuid, device, configdrive):
cur_parts = set(part['number'] for part in list_partitions(device))
if _is_disk_gpt_partitioned(device, node_uuid):
_fix_gpt_structs(device, node_uuid)
create_option = '0:-%dMB:0' % MAX_CONFIG_DRIVE_SIZE_MB
utils.execute('sgdisk', '-n', create_option, device,
run_as_root=True)

View File

@ -997,6 +997,8 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
autospec=True)
@mock.patch.object(disk_utils, 'dd',
autospec=True)
@mock.patch.object(disk_utils, 'fix_gpt_partition',
autospec=True)
@mock.patch.object(disk_utils, '_fix_gpt_structs',
autospec=True)
@mock.patch.object(disk_utils, '_is_disk_gpt_partitioned',
@ -1009,8 +1011,8 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
autospec=True)
def test_create_partition_exists(self, mock_get_configdrive,
mock_get_labelled_partition,
mock_list_partitions,
mock_is_disk_gpt, mock_fix_gpt,
mock_list_partitions, mock_is_disk_gpt,
mock_fix_gpt, mock_fix_gpt_partition,
mock_dd, mock_unlink, mock_execute):
config_url = 'http://1.2.3.4/cd'
configdrive_part = '/dev/fake-part1'
@ -1021,13 +1023,15 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
mock_get_configdrive.return_value = (configdrive_mb, configdrive_file)
disk_utils.create_config_drive_partition(self.node_uuid, self.dev,
config_url)
mock_fix_gpt_partition.assert_called_with(self.dev, self.node_uuid)
mock_get_configdrive.assert_called_with(config_url, self.node_uuid)
mock_get_labelled_partition.assert_called_with(self.dev,
self.config_part_label,
self.node_uuid)
self.assertFalse(mock_list_partitions.called)
self.assertFalse(mock_is_disk_gpt.called)
self.assertFalse(mock_execute.called)
self.assertFalse(mock_is_disk_gpt.called)
self.assertFalse(mock_fix_gpt.called)
mock_dd.assert_called_with(configdrive_file, configdrive_part)
mock_unlink.assert_called_with(configdrive_file)
@ -1036,6 +1040,8 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
autospec=True)
@mock.patch.object(disk_utils, 'dd',
autospec=True)
@mock.patch.object(disk_utils, 'fix_gpt_partition',
autospec=True)
@mock.patch.object(disk_utils, '_fix_gpt_structs',
autospec=True)
@mock.patch.object(disk_utils, '_is_disk_gpt_partitioned',
@ -1049,8 +1055,8 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
def test_create_partition_gpt(self, mock_get_configdrive,
mock_get_labelled_partition,
mock_list_partitions, mock_is_disk_gpt,
mock_fix_gpt, mock_dd, mock_unlink,
mock_execute):
mock_fix_gpt, mock_fix_gpt_partition,
mock_dd, mock_unlink, mock_execute):
config_url = 'http://1.2.3.4/cd'
configdrive_file = '/tmp/xyz'
configdrive_mb = 10
@ -1091,7 +1097,9 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
self.assertEqual(2, mock_list_partitions.call_count)
mock_is_disk_gpt.assert_called_with(self.dev, self.node_uuid)
mock_fix_gpt.assert_called_with(self.dev, self.node_uuid)
mock_fix_gpt_partition.assert_called_with(self.dev, self.node_uuid)
self.assertFalse(mock_fix_gpt.called)
mock_fix_gpt_partition.assert_called_with(self.dev, self.node_uuid)
mock_dd.assert_called_with(configdrive_file, expected_part)
mock_unlink.assert_called_with(configdrive_file)
@ -1104,6 +1112,8 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
autospec=True)
@mock.patch.object(disk_utils, '_is_disk_larger_than_max_size',
autospec=True)
@mock.patch.object(disk_utils, 'fix_gpt_partition',
autospec=True)
@mock.patch.object(disk_utils, '_fix_gpt_structs',
autospec=True)
@mock.patch.object(disk_utils, '_is_disk_gpt_partitioned',
@ -1118,6 +1128,7 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
mock_get_labelled_partition,
mock_list_partitions,
mock_is_disk_gpt, mock_fix_gpt,
mock_fix_gpt_partition,
mock_disk_exceeds, mock_dd,
mock_unlink, mock_log, mock_execute,
mock_count, disk_size_exceeds_max=False,
@ -1186,10 +1197,12 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
])
self.assertEqual(2, mock_list_partitions.call_count)
mock_is_disk_gpt.assert_called_with(self.dev, self.node_uuid)
mock_fix_gpt_partition.assert_called_with(self.dev, self.node_uuid)
mock_disk_exceeds.assert_called_with(self.dev, self.node_uuid)
mock_dd.assert_called_with(configdrive_file, expected_part)
mock_unlink.assert_called_with(configdrive_file)
self.assertFalse(mock_fix_gpt.called)
self.assertFalse(mock_fix_gpt.called)
mock_count.assert_called_with(self.dev)
def test__create_partition_mbr_disk_under_2TB(self):
@ -1220,6 +1233,8 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
autospec=True)
@mock.patch.object(disk_utils, '_is_disk_larger_than_max_size',
autospec=True)
@mock.patch.object(disk_utils, 'fix_gpt_partition',
autospec=True)
@mock.patch.object(disk_utils, '_fix_gpt_structs',
autospec=True)
@mock.patch.object(disk_utils, '_is_disk_gpt_partitioned',
@ -1234,6 +1249,7 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
mock_get_labelled_partition,
mock_list_partitions,
mock_is_disk_gpt, mock_fix_gpt,
mock_fix_gpt_partition,
mock_disk_exceeds, mock_dd,
mock_unlink, mock_execute,
mock_count):
@ -1276,6 +1292,7 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
'fat32', '-64MiB', '-0',
run_as_root=True)
self.assertEqual(2, mock_list_partitions.call_count)
mock_fix_gpt_partition.assert_called_with(self.dev, self.node_uuid)
mock_is_disk_gpt.assert_called_with(self.dev, self.node_uuid)
mock_disk_exceeds.assert_called_with(self.dev, self.node_uuid)
self.assertFalse(mock_fix_gpt.called)
@ -1291,6 +1308,8 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
autospec=True)
@mock.patch.object(disk_utils, '_is_disk_larger_than_max_size',
autospec=True)
@mock.patch.object(disk_utils, 'fix_gpt_partition',
autospec=True)
@mock.patch.object(disk_utils, '_fix_gpt_structs',
autospec=True)
@mock.patch.object(disk_utils, '_is_disk_gpt_partitioned',
@ -1305,6 +1324,7 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
mock_get_labelled_partition,
mock_list_partitions,
mock_is_disk_gpt, mock_fix_gpt,
mock_fix_gpt_partition,
mock_disk_exceeds, mock_dd,
mock_unlink, mock_execute,
mock_count):
@ -1341,6 +1361,7 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
'fat32', '-64MiB', '-0',
run_as_root=True)
self.assertEqual(1, mock_list_partitions.call_count)
mock_fix_gpt_partition.assert_called_with(self.dev, self.node_uuid)
mock_is_disk_gpt.assert_called_with(self.dev, self.node_uuid)
mock_disk_exceeds.assert_called_with(self.dev, self.node_uuid)
self.assertFalse(mock_fix_gpt.called)
@ -1353,6 +1374,8 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
autospec=True)
@mock.patch.object(disk_utils, 'dd',
autospec=True)
@mock.patch.object(disk_utils, 'fix_gpt_partition',
autospec=True)
@mock.patch.object(disk_utils, '_fix_gpt_structs',
autospec=True)
@mock.patch.object(disk_utils, '_is_disk_gpt_partitioned',
@ -1367,6 +1390,7 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
mock_get_labelled_partition,
mock_list_partitions,
mock_is_disk_gpt, mock_fix_gpt,
mock_fix_gpt_partition,
mock_dd, mock_unlink,
mock_count):
config_url = 'http://1.2.3.4/cd'
@ -1396,6 +1420,7 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
mock_get_configdrive.assert_called_with(config_url, self.node_uuid)
self.assertEqual(1, mock_list_partitions.call_count)
mock_fix_gpt_partition.assert_called_with(self.dev, self.node_uuid)
mock_is_disk_gpt.assert_called_with(self.dev, self.node_uuid)
self.assertFalse(mock_fix_gpt.called)
self.assertFalse(mock_dd.called)
@ -1431,6 +1456,8 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
@mock.patch.object(utils, 'execute', autospec=True)
@mock.patch.object(utils, 'unlink_without_raise',
autospec=True)
@mock.patch.object(disk_utils, 'fix_gpt_partition',
autospec=True)
@mock.patch.object(disk_utils, '_is_disk_gpt_partitioned',
autospec=True)
@mock.patch.object(disk_utils, '_get_labelled_partition',
@ -1439,7 +1466,8 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
autospec=True)
def test_create_partition_conf_drive_error_counting(
self, mock_get_configdrive, mock_get_labelled_partition,
mock_is_disk_gpt, mock_unlink, mock_execute, mock_count):
mock_is_disk_gpt, mock_fix_gpt_partition,
mock_unlink, mock_execute, mock_count):
config_url = 'http://1.2.3.4/cd'
configdrive_file = '/tmp/xyz'
configdrive_mb = 10
@ -1456,5 +1484,6 @@ class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
mock_get_configdrive.assert_called_with(config_url, self.node_uuid)
mock_unlink.assert_called_with(configdrive_file)
mock_fix_gpt_partition.assert_called_with(self.dev, self.node_uuid)
mock_is_disk_gpt.assert_called_with(self.dev, self.node_uuid)
mock_count.assert_called_once_with(self.dev)