diff --git a/proliantutils/hpssa/manager.py b/proliantutils/hpssa/manager.py index 4f873d2..15179b0 100644 --- a/proliantutils/hpssa/manager.py +++ b/proliantutils/hpssa/manager.py @@ -74,6 +74,29 @@ def validate(raid_config): raise exception.InvalidInputError(msg) +def _filter_raid_mode_controllers(server): + """Filters out the hpssa controllers in raid mode. + + This method updates the server with only the controller which is in raid + mode. The controller which are in HBA mode are removed from the list. + + :param server: The object containing all the supported hpssa controllers + details. + :raises exception.HPSSAOperationError, if all the controller are in HBA + mode. + """ + all_controllers = server.controllers + non_hba_controllers = [c for c in all_controllers + if not c.properties.get('HBA Mode Enabled', False)] + + if not non_hba_controllers: + reason = ("None of the available HPSSA controllers %s have RAID " + "enabled" % ', '.join([c.id for c in all_controllers])) + raise exception.HPSSAOperationError(reason=reason) + + server.controllers = non_hba_controllers + + def create_configuration(raid_config): """Create a RAID configuration on this server. @@ -89,11 +112,15 @@ def create_configuration(raid_config): controller, physical_disks, etc filled for each logical disk after its creation. :raises exception.InvalidInputError, if input is invalid. + :raises exception.HPSSAOperationError, if all the controllers are in HBA + mode. """ - validate(raid_config) - server = objects.Server() + _filter_raid_mode_controllers(server) + + validate(raid_config) + # Make sure we create the large disks first. This is avoid the # situation that we avoid giving large disks to smaller requests. # For example, consider this: @@ -265,6 +292,9 @@ def delete_configuration(): the logical disks. """ server = objects.Server() + + _filter_raid_mode_controllers(server) + for controller in server.controllers: # Trigger delete only if there is some RAID array, otherwise # hpssacli will fail saying "no logical drives found." diff --git a/proliantutils/tests/hpssa/raid_constants.py b/proliantutils/tests/hpssa/raid_constants.py index a714afa..d47baeb 100644 --- a/proliantutils/tests/hpssa/raid_constants.py +++ b/proliantutils/tests/hpssa/raid_constants.py @@ -2231,3 +2231,81 @@ Smart Array P822 in Slot 3 Serial Number: 2AVVENJN Model: HP EF0600FATFF ''' + +HPSSA_HBA_MODE = ''' + +Smart Array P822 in Slot 3 + Bus Interface: PCI + Slot: 3 + Serial Number: PDVTF0BRH5T0KV + Cache Serial Number: PBKUD0BRH5T3UM + RAID 6 (ADG) Status: Enabled + Controller Status: OK + Hardware Revision: B + Firmware Version: 5.22 + Cache Board Present: True + Cache Status: Not Configured + Total Cache Size: 2.0 GB + Total Cache Memory Available: 1.8 GB + Cache Backup Power Source: Capacitors + Battery/Capacitor Count: 1 + Battery/Capacitor Status: OK + Controller Temperature (C): 88 + Cache Module Temperature (C): 37 + Capacitor Temperature (C): 24 + Number of Ports: 6 (2 Internal / 4 External ) + Driver Name: hpsa + Driver Version: 3.4.14 + HBA Mode Enabled: True + PCI Address (Domain:Bus:Device.Function): 0000:0D:00.0 + Host Serial Number: SGH401AERD + Sanitize Erase Supported: False + Primary Boot Volume: None + Secondary Boot Volume: None + + + Port Name: 5I + Port ID: 0 + Port Connection Number: 0 + SAS Address: 5001438028842E40 + Port Location: Internal + + Internal Drive Cage at Port 5I, Box 1, OK + Power Supply Status: Not Redundant + Drive Bays: 4 + Port: 5I + Box: 1 + Location: Internal + + Physical Drives + physicaldrive 5I:1:1 (port 5I:box 1:bay 1, SAS, 600 GB, OK) + + + + unassigned + + physicaldrive 5I:1:1 + Port: 5I + Box: 1 + Bay: 1 + Status: OK + Drive Type: HBA Mode Drive + Interface Type: SAS + Size: 600 GB + Drive exposed to OS: True + Native Block Size: 512 + Rotational Speed: 15000 + Firmware Revision: HPD6 + Serial Number: 6SL7G4QV0000B41803GZ + Model: HP EF0600FARNA + Current Temperature (C): 36 + Maximum Temperature (C): 45 + PHY Count: 2 + PHY Transfer Rate: 6.0Gbps, Unknown + Drive Authentication Status: OK + Carrier Application Version: 11 + Carrier Bootloader Version: 6 + Disk Name: /dev/sda + Mount Points: None + Sanitize Erase Supported: False +''' diff --git a/proliantutils/tests/hpssa/test_manager.py b/proliantutils/tests/hpssa/test_manager.py index e888474..ad2bac4 100644 --- a/proliantutils/tests/hpssa/test_manager.py +++ b/proliantutils/tests/hpssa/test_manager.py @@ -104,6 +104,8 @@ class ManagerTestCases(testtools.TestCase): def test_create_configuration_invalid_logical_disks(self, get_all_details_mock): + drives = raid_constants.HPSSA_NO_DRIVES + get_all_details_mock.return_value = drives raid_info = {} self.assertRaises(exception.InvalidInputError, manager.create_configuration, @@ -167,6 +169,20 @@ class ManagerTestCases(testtools.TestCase): raid_info) self.assertIn("of size 50 GB and raid level 1", str(exc)) + def test_create_configuration_hba_enabled(self, get_all_details_mock): + drives = raid_constants.HPSSA_HBA_MODE + get_all_details_mock.return_value = drives + + raid_info = {'logical_disks': 'foo'} + + msg = ("An error was encountered while doing hpssa configuration: None" + " of the available HPSSA controllers Smart Array P822 in " + "Slot 3 have RAID enabled") + ex = self.assertRaises(exception.HPSSAOperationError, + manager.create_configuration, + raid_info) + self.assertIn(msg, str(ex)) + @mock.patch.object(objects.Controller, 'execute_cmd') def test_create_configuration_share_physical_disks( self, controller_exec_cmd_mock, get_all_details_mock): @@ -368,6 +384,19 @@ class ManagerTestCases(testtools.TestCase): get_configuration_mock.assert_called_once_with() self.assertEqual('foo', ret) + @mock.patch.object(manager, 'get_configuration') + def test_delete_configuration_hba_enabled(self, get_configuration, + get_all_details_mock): + drives = raid_constants.HPSSA_HBA_MODE + get_all_details_mock.return_value = drives + + msg = ("An error was encountered while doing hpssa configuration: None" + " of the available HPSSA controllers Smart Array P822 in " + "Slot 3 have RAID enabled") + ex = self.assertRaises(exception.HPSSAOperationError, + manager.delete_configuration) + self.assertIn(msg, str(ex)) + def test_get_configuration(self, get_all_details_mock): get_all_details_mock.return_value = raid_constants.HPSSA_ONE_DRIVE @@ -410,6 +439,28 @@ class ManagerTestCases(testtools.TestCase): self.assertEqual(sorted(pds_active_expected), sorted(pds_active)) self.assertEqual(sorted(pds_ready_expected), sorted(pds_ready)) + def test__filter_raid_mode_controllers_hba(self, get_all_details_mock): + get_all_details_mock.return_value = raid_constants.HPSSA_HBA_MODE + + server = objects.Server() + + msg = ("An error was encountered while doing hpssa configuration: None" + " of the available HPSSA controllers Smart Array P822 in " + "Slot 3 have RAID enabled") + ex = self.assertRaises(exception.HPSSAOperationError, + manager._filter_raid_mode_controllers, + server) + self.assertIn(msg, str(ex)) + + def test__filter_raid_mode_controllers(self, get_all_details_mock): + get_all_details_mock.return_value = raid_constants.HPSSA_NO_DRIVES + + server = objects.Server() + ctrl_expected = server.controllers + + manager._filter_raid_mode_controllers(server) + self.assertEqual(ctrl_expected, server.controllers) + class RaidConfigValidationTestCases(testtools.TestCase):