summaryrefslogtreecommitdiff
path: root/ironic_python_agent
diff options
context:
space:
mode:
authorArne Wiebalck <Arne.Wiebalck@cern.ch>2019-07-26 14:47:15 +0200
committerArne Wiebalck <Arne.Wiebalck@cern.ch>2019-08-16 11:35:07 +0200
commit9dca5d76b3a0f2cab2fe6171d844944e065a6741 (patch)
tree1ee565dd5f665145215d22b355e4f55d29565fb9 /ironic_python_agent
parentef831847e6b07753b4916db79e0d60f34d55724c (diff)
downloadironic-python-agent-9dca5d76b3a0f2cab2fe6171d844944e065a6741.tar.gz
Software RAID: Ignore missing component devices or holder disks
With the addition of devices with type 'MD' during list_all_block_devices (for "empty" devices), partitions on top of md devices are now returned as well. These don't need deletion, so skip these during software RAID cleanup. Story: #2006355 Task: #36121 Change-Id: Idff9b9b0cbe42b57aa315ae07c0b51c35c9ade1e
Diffstat (limited to 'ironic_python_agent')
-rw-r--r--ironic_python_agent/hardware.py26
-rw-r--r--ironic_python_agent/tests/unit/test_hardware.py13
2 files changed, 31 insertions, 8 deletions
diff --git a/ironic_python_agent/hardware.py b/ironic_python_agent/hardware.py
index 9ed0c5b8..bbaf9ee9 100644
--- a/ironic_python_agent/hardware.py
+++ b/ironic_python_agent/hardware.py
@@ -127,15 +127,16 @@ def _get_component_devices(raid_device):
if not raid_device:
return []
- component_devices = []
try:
out, _ = utils.execute('mdadm', '--detail', raid_device,
use_standard_locale=True)
except processutils.ProcessExecutionError as e:
msg = ('Could not get component devices of %(dev)s: %(err)s' %
{'dev': raid_device, 'err': e})
- raise errors.SoftwareRAIDError(msg)
+ LOG.warning(msg)
+ return []
+ component_devices = []
lines = out.splitlines()
# the first line contains the md device itself
for line in lines[1:]:
@@ -156,16 +157,16 @@ def get_holder_disks(raid_device):
if not raid_device:
return []
- holder_disks = []
-
try:
out, _ = utils.execute('mdadm', '--detail', raid_device,
use_standard_locale=True)
except processutils.ProcessExecutionError as e:
msg = ('Could not get holder disks of %(dev)s: %(err)s' %
{'dev': raid_device, 'err': e})
- raise errors.SoftwareRAIDError(msg)
+ LOG.warning(msg)
+ return []
+ holder_disks = []
lines = out.splitlines()
# the first line contains the md device itself
for line in lines[1:]:
@@ -1549,12 +1550,21 @@ class GenericHardwareManager(HardwareManager):
raid_devices = list_all_block_devices(block_type='raid',
ignore_raid=False)
for raid_device in raid_devices:
+ component_devices = _get_component_devices(raid_device.name)
+ if not component_devices:
+ # A "Software RAID device" without components is usually
+ # a partition on an md device (as, for instance, created
+ # by the conductor for the config drive). This will be
+ # cleaned with the hosting md device.
+ msg = ("Software RAID cleaning is skipping "
+ "partition %s" % raid_device.name)
+ LOG.info(msg)
+ continue
+ holder_disks = get_holder_disks(raid_device.name)
+
LOG.info("Deleting Software RAID device {}".format(
raid_device.name))
-
- component_devices = _get_component_devices(raid_device.name)
LOG.debug('Found component devices %s', component_devices)
- holder_disks = get_holder_disks(raid_device.name)
LOG.debug('Found holder disks %s', holder_disks)
# Remove md devices.
diff --git a/ironic_python_agent/tests/unit/test_hardware.py b/ironic_python_agent/tests/unit/test_hardware.py
index f540f1f5..49cae296 100644
--- a/ironic_python_agent/tests/unit/test_hardware.py
+++ b/ironic_python_agent/tests/unit/test_hardware.py
@@ -2955,6 +2955,19 @@ class TestGenericHardwareManager(base.IronicAgentTest):
mock.call('wipefs', '-af', '/dev/sda'),
mock.call('wipefs', '-af', '/dev/sdb')])
+ @mock.patch.object(hardware, '_get_component_devices', autospec=True)
+ @mock.patch.object(hardware, 'list_all_block_devices', autospec=True)
+ @mock.patch.object(utils, 'execute', autospec=True)
+ def test_delete_configuration_partition(self, mocked_execute, mocked_list,
+ mocked_get_component):
+ raid_device1_part1 = hardware.BlockDevice('/dev/md0p1', 'RAID-1',
+ 1073741824, True)
+ hardware.list_all_block_devices.return_value = [raid_device1_part1]
+ mocked_get_component.return_value = []
+
+ self.assertIsNone(self.hardware.delete_configuration(self.node, []))
+ mocked_execute.assert_has_calls([])
+
@mock.patch.object(utils, 'execute', autospec=True)
def test_validate_configuration_valid_raid1(self, mocked_execute):
raid_config = {