summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Szumski <doug@stackhpc.com>2020-07-09 14:11:28 +0100
committerJulia Kreger <juliaashleykreger@gmail.com>2020-07-22 11:16:13 -0700
commit5e95b1321d6e4fe5c562092d0baba73ad6d5303e (patch)
tree740a0c357949a93062e697649e35e55fddd363a8
parentc66bec0f43cfeb371a8ac97df3eddca3853191dc (diff)
downloadironic-python-agent-5e95b1321d6e4fe5c562092d0baba73ad6d5303e.tar.gz
Fix bootloader install issue with MDRAID
When no root_device hint is set, an MDRAID partition can be incorrectly selected as the root device which causes installation of the bootloader to the physical disks behind the MDRAID volume to fail. See the notes in the referenced Story for more detail. This change adds a little more specificity to the listing of block devices. Change-Id: I66db457e71a0586723ee753bef961aec5bf58827 Story: 2007905 Task: 40303
-rw-r--r--ironic_python_agent/hardware.py30
-rw-r--r--ironic_python_agent/tests/unit/test_hardware.py21
-rw-r--r--releasenotes/notes/fix-bootloader-install-with-mdraid-0a254035df9d0bed.yaml7
3 files changed, 52 insertions, 6 deletions
diff --git a/ironic_python_agent/hardware.py b/ironic_python_agent/hardware.py
index d11b0443..ea06bb40 100644
--- a/ironic_python_agent/hardware.py
+++ b/ironic_python_agent/hardware.py
@@ -380,12 +380,24 @@ def list_all_block_devices(block_type='disk',
# Other possible type values, which we skip recording:
# lvm, part, rom, loop
if devtype != block_type:
- if (devtype is not None
- and any(x in devtype for x in ['raid', 'md'])
- and not ignore_raid):
+ if (devtype is None or ignore_raid):
+ LOG.debug("Skipping: {!r}".format(line))
+ continue
+ elif ('raid' in devtype
+ and block_type in ['raid', 'disk']):
LOG.debug(
- "TYPE detected to contain 'raid' or 'md', signifying a "
+ "TYPE detected to contain 'raid', signifying a "
"RAID volume. Found: {!r}".format(line))
+ elif (devtype == 'md'
+ and (block_type == 'part'
+ or block_type == 'md')):
+ # NOTE(dszumski): Partitions on software RAID devices have type
+ # 'md'. This may also contain RAID devices in a broken state in
+ # rare occasions. See https://review.opendev.org/#/c/670807 for
+ # more detail.
+ LOG.debug(
+ "TYPE detected to contain 'md', signifying a "
+ "RAID partition. Found: {!r}".format(line))
else:
LOG.debug(
"TYPE did not match. Wanted: {!r} but found: {!r}".format(
@@ -1790,6 +1802,16 @@ class GenericHardwareManager(HardwareManager):
raid_devices = list_all_block_devices(block_type='raid',
ignore_raid=False,
ignore_empty=False)
+ # NOTE(dszumski): Fetch all devices of type 'md'. This
+ # will generally contain partitions on a software RAID
+ # device, but crucially may also contain devices in a
+ # broken state. See https://review.opendev.org/#/c/670807/
+ # for more detail.
+ raid_devices.extend(
+ list_all_block_devices(block_type='md',
+ ignore_raid=False,
+ ignore_empty=False)
+ )
return raid_devices
raid_devices = _scan_raids()
diff --git a/ironic_python_agent/tests/unit/test_hardware.py b/ironic_python_agent/tests/unit/test_hardware.py
index de4fdaf8..63ccb1d0 100644
--- a/ironic_python_agent/tests/unit/test_hardware.py
+++ b/ironic_python_agent/tests/unit/test_hardware.py
@@ -159,13 +159,24 @@ BLK_DEVICE_TEMPLATE_SMALL_DEVICES = [
# NOTE(TheJulia): This list intentionally contains duplicates
# as the code filters them out by kernel device name.
+# NOTE(dszumski): We include some partitions here to verify that
+# they are filtered out when not requested. It is assumed that
+# ROTA has been set to 0 on some software RAID devices for testing
+# purposes. In practice is appears to inherit from the underyling
+# devices, so in this example it would normally be 1.
RAID_BLK_DEVICE_TEMPLATE = (
'KNAME="sda" MODEL="DRIVE 0" SIZE="1765517033472" '
'ROTA="1" TYPE="disk"\n'
+ 'KNAME="sda1" MODEL="DRIVE 0" SIZE="107373133824" '
+ 'ROTA="1" TYPE="part"\n'
'KNAME="sdb" MODEL="DRIVE 1" SIZE="1765517033472" '
'ROTA="1" TYPE="disk"\n'
'KNAME="sdb" MODEL="DRIVE 1" SIZE="1765517033472" '
'ROTA="1" TYPE="disk"\n'
+ 'KNAME="sdb1" MODEL="DRIVE 1" SIZE="107373133824" '
+ 'ROTA="1" TYPE="part"\n'
+ 'KNAME="md0p1" MODEL="RAID" SIZE="107236818944" '
+ 'ROTA="0" TYPE="md"\n'
'KNAME="md0" MODEL="RAID" SIZE="1765517033470" '
'ROTA="0" TYPE="raid1"\n'
'KNAME="md0" MODEL="RAID" SIZE="1765517033470" '
@@ -3843,9 +3854,11 @@ class TestGenericHardwareManager(base.IronicAgentTest):
hardware.list_all_block_devices.side_effect = [
[raid_device1, raid_device2], # list_all_block_devices raid
+ [], # list_all_block_devices raid (md)
[sda, sdb, sdc], # list_all_block_devices disks
[], # list_all_block_devices parts
[], # list_all_block_devices raid
+ [], # list_all_block_devices raid (md)
]
mocked_get_component.side_effect = [
["/dev/sda1", "/dev/sdb1"],
@@ -3925,13 +3938,14 @@ class TestGenericHardwareManager(base.IronicAgentTest):
raid_device1_part1 = hardware.BlockDevice('/dev/md0p1', 'RAID-1',
1073741824, True)
hardware.list_all_block_devices.side_effect = [
- [raid_device1_part1], # list_all_block_devices raid
+ [], # list_all_block_devices raid
+ [raid_device1_part1], # list_all_block_devices raid (md)
[], # list_all_block_devices disks
[], # list_all_block_devices parts
[], # list_all_block_devices raid
+ [], # list_all_block_devices raid (md)
]
mocked_get_component.return_value = []
-
self.assertIsNone(self.hardware.delete_configuration(self.node, []))
mocked_execute.assert_has_calls([
mock.call('mdadm', '--assemble', '--scan', check_exit_code=False),
@@ -3952,12 +3966,15 @@ class TestGenericHardwareManager(base.IronicAgentTest):
hardware.list_all_block_devices.side_effect = [
[raid_device1], # list_all_block_devices raid
+ [], # list_all_block_devices raid (type md)
[], # list_all_block_devices disks
[], # list_all_block_devices parts
[raid_device1], # list_all_block_devices raid
+ [], # list_all_block_devices raid (type md)
[], # list_all_block_devices disks
[], # list_all_block_devices parts
[raid_device1], # list_all_block_devices raid
+ [], # list_all_block_devices raid (type md)
]
mocked_get_component.return_value = []
diff --git a/releasenotes/notes/fix-bootloader-install-with-mdraid-0a254035df9d0bed.yaml b/releasenotes/notes/fix-bootloader-install-with-mdraid-0a254035df9d0bed.yaml
new file mode 100644
index 00000000..b9a1f685
--- /dev/null
+++ b/releasenotes/notes/fix-bootloader-install-with-mdraid-0a254035df9d0bed.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Fixes an issue where the bootloader installation can fail on a software
+ RAID volume when no root_device hint is set.
+ See `Story 2007905
+ <https://storyboard.openstack.org/#!/story/2007905>`_