From c5fbf0702b81bebb43a143a89e120f5846821b1d Mon Sep 17 00:00:00 2001 From: Christopher Dearborn Date: Fri, 29 Jun 2018 10:06:08 -0400 Subject: [PATCH] iDRAC RAID10 creation with greater than 16 drives This patch enables creation of large RAID10's with greater than 16 drives when using the iDRAC hardware type. Best practice is to not pass span length and span depth when creating a RAID10. In this case, the iDRAC will calculate these values using information queried from the RAID controller. See this white paper on intelligent mirroring for more information: https://www.dell.com/support/article/us/en/04/sln111362/ intelligent-mirroring-and-enhanced-raid-10-aka-raid-10e-?lang=en Change-Id: If1fb29f8a078fdb0cb0338c86e32158093cad22e Task: # 22634 Story: #2002771 --- ironic/drivers/modules/drac/raid.py | 10 +++- .../unit/drivers/modules/drac/test_raid.py | 53 ++++++++++++++++++- ...eater-than-16-drives-a4cb107e34371a51.yaml | 6 +++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/drac-fix-raid10-greater-than-16-drives-a4cb107e34371a51.yaml diff --git a/ironic/drivers/modules/drac/raid.py b/ironic/drivers/modules/drac/raid.py index 4b54480691..9cc49cb8fb 100644 --- a/ironic/drivers/modules/drac/raid.py +++ b/ironic/drivers/modules/drac/raid.py @@ -497,8 +497,14 @@ def _calculate_volume_props(logical_disk, physical_disks, free_space_mb): disks_per_span = len(selected_disks) / spans_count - logical_disk['span_depth'] = spans_count - logical_disk['span_length'] = disks_per_span + # Best practice is to not pass span_length and span_depth when creating a + # RAID10. The iDRAC will dynamically calculate these values using maximum + # values obtained from the RAID controller. + logical_disk['span_depth'] = None + logical_disk['span_length'] = None + if logical_disk['raid_level'] != '1+0': + logical_disk['span_depth'] = spans_count + logical_disk['span_length'] = disks_per_span max_volume_size_mb = _max_volume_size_mb( logical_disk['raid_level'], selected_disks, free_space_mb, diff --git a/ironic/tests/unit/drivers/modules/drac/test_raid.py b/ironic/tests/unit/drivers/modules/drac/test_raid.py index a713cccd6a..b86ab5f7d7 100644 --- a/ironic/tests/unit/drivers/modules/drac/test_raid.py +++ b/ironic/tests/unit/drivers/modules/drac/test_raid.py @@ -661,6 +661,57 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest): mock_client = mock.Mock() mock_get_drac_client.return_value = mock_client + self.root_logical_disk = { + 'size_gb': 100, + 'raid_level': '5+0', + 'is_root_volume': True + } + self.logical_disks = [self.root_logical_disk] + self.target_raid_configuration = {'logical_disks': self.logical_disks} + self.node.target_raid_config = self.target_raid_configuration + self.node.save() + + physical_disks = self._generate_physical_disks() + mock_list_physical_disks.return_value = physical_disks + + mock_commit_config.return_value = '42' + + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + task.driver.raid.create_configuration( + task, create_root_volume=True, create_nonroot_volumes=True) + + mock_client.create_virtual_disk.assert_called_once_with( + 'RAID.Integrated.1-1', + ['Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1', + 'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1', + 'Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1', + 'Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1', + 'Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1', + 'Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1'], + '5+0', 102400, None, 3, 2) + + # Commits to the controller + mock_commit_config.assert_called_once_with( + mock.ANY, raid_controller='RAID.Integrated.1-1', reboot=True) + + self.node.refresh() + self.assertEqual(['42'], + self.node.driver_internal_info['raid_config_job_ids']) + + @mock.patch.object(drac_common, 'get_drac_client', spec_set=True, + autospec=True) + @mock.patch.object(drac_raid, 'list_physical_disks', autospec=True) + @mock.patch.object(drac_job, 'validate_job_queue', spec_set=True, + autospec=True) + @mock.patch.object(drac_raid, 'commit_config', spec_set=True, + autospec=True) + def test_create_configuration_with_nested_raid_10( + self, mock_commit_config, mock_validate_job_queue, + mock_list_physical_disks, mock_get_drac_client): + mock_client = mock.Mock() + mock_get_drac_client.return_value = mock_client + self.root_logical_disk = { 'size_gb': 100, 'raid_level': '1+0', @@ -687,7 +738,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest): 'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1', 'Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1', 'Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1'], - '1+0', 102400, None, 2, 2) + '1+0', 102400, None, None, None) # Commits to the controller mock_commit_config.assert_called_once_with( diff --git a/releasenotes/notes/drac-fix-raid10-greater-than-16-drives-a4cb107e34371a51.yaml b/releasenotes/notes/drac-fix-raid10-greater-than-16-drives-a4cb107e34371a51.yaml new file mode 100644 index 0000000000..d34c912040 --- /dev/null +++ b/releasenotes/notes/drac-fix-raid10-greater-than-16-drives-a4cb107e34371a51.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixes an issue where RAID 10 creation fails with greater than 16 drives + when using the ``idrac`` hardware type. See bug `2002771 + `_ for details.