diff --git a/proliantutils/functests/test_hpssa.py b/proliantutils/functests/test_hpssa.py index 18878230..cb2fde0d 100644 --- a/proliantutils/functests/test_hpssa.py +++ b/proliantutils/functests/test_hpssa.py @@ -18,6 +18,7 @@ import stat from oslo.concurrency import processutils import testtools +from proliantutils.hpssa import constants from proliantutils.hpssa import manager from proliantutils.hpssa import objects @@ -31,8 +32,6 @@ class HPSSATestCase(testtools.TestCase): def _get_server(self): server = objects.Server() - if not server.controllers: - self.fail("No controllers detected on the server.") return server def _get_physical_drives(self, server, no_of_physical_drives_required, @@ -50,7 +49,7 @@ class HPSSATestCase(testtools.TestCase): return physical_drives[:no_of_physical_drives_required] - def test_create_configuration_single_logical_drive(self): + def _test_create_configuration_single_logical_drive(self, raid_level): server = self._get_server() size_gb = 100 @@ -58,56 +57,74 @@ class HPSSATestCase(testtools.TestCase): manager.delete_configuration() devices_before_create = set(glob.glob('/dev/sd[a-z]')) - for raid_level in ['0', '1', '5', '6']: - self._get_physical_drives(server, 2, size_gb) + minimum_disks_required = constants.RAID_LEVEL_MIN_DISKS[raid_level] + self._get_physical_drives(server, minimum_disks_required, size_gb) - raid_config = { - 'logical_disks': - [{'size_gb': size_gb, - 'raid_level': raid_level}] - } + raid_config = { + 'logical_disks': [{'size_gb': size_gb, 'raid_level': raid_level}]} - current_config = manager.create_configuration(raid_config) + current_config = manager.create_configuration(raid_config) - logical_disk = current_config['logical_disks'][0] - self.assertIsNotNone(logical_disk['root_device_hint']) - self.assertIsNotNone(logical_disk['volume_name']) + logical_disk = current_config['logical_disks'][0] + self.assertIsNotNone(logical_disk['root_device_hint']) + self.assertIsNotNone(logical_disk['volume_name']) - devices_after_create = set(glob.glob('/dev/sd[a-z]')) - new_device = devices_after_create - devices_before_create + devices_after_create = set(glob.glob('/dev/sd[a-z]')) + new_device = devices_after_create - devices_before_create - # Make sure only one new device appeared now. - if len(new_device) != 1: - self.fail("More than 1 block devices were found after " - "creating RAID volume") + # Make sure only one new device appeared now. + if len(new_device) != 1: + self.fail("More than 1 block devices were found after " + "creating RAID volume") - new_device_file = new_device.pop() - s = os.stat(new_device_file) - if not stat.S_ISBLK(s.st_mode): - self.fail("Newly created disk %s is not a block device" - % new_device_file) + new_device_file = new_device.pop() + s = os.stat(new_device_file) + if not stat.S_ISBLK(s.st_mode): + self.fail("Newly created disk %s is not a block device" + % new_device_file) - # SCSI disk devices have major number 8 - # https://www.kernel.org/doc/Documentation/devices.txt - # TODO(rameshg87: Need to check if any more assetions need to be - # done on the newly created disk device. - self.assertEqual(8, os.major(s.st_rdev)) + # SCSI disk devices have major number 8 + # https://www.kernel.org/doc/Documentation/devices.txt + # TODO(rameshg87: Need to check if any more assetions need to be + # done on the newly created disk device. + self.assertEqual(8, os.major(s.st_rdev)) - stdout, stderr = processutils.execute("lsblk", "-Pio", "SIZE", - new_device_file) - # Output is like (two times printed): - # SIZE="8G" - # SIZE="8G" - created_disk_size = stdout.split("\n")[0].split('"')[1][:-1] - self.assertEqual(size_gb, int(created_disk_size)) + stdout, stderr = processutils.execute("lsblk", "-Pio", "SIZE", + new_device_file) + # Output is like (two times printed): + # SIZE="8G" + # SIZE="8G" + created_disk_size = stdout.split("\n")[0].split('"')[1][:-1] + self.assertEqual(size_gb, int(created_disk_size)) - stdout, stderr = processutils.execute("lsblk", "-Pio", "WWN", - new_device_file) - # Output is like: - # WWN="0x600508b1001cca7f" - # TODO(rameshg87: Check with hpssa team whether this can be - # assumed. - wwn = stdout.split("\n")[0].split('"')[1] - self.assertEqual(logical_disk['root_device_hint']['wwn'], wwn) + stdout, stderr = processutils.execute("lsblk", "-Pio", "WWN", + new_device_file) + # Output is like: + # WWN="0x600508b1001cca7f" + # TODO(rameshg87: Check with hpssa team whether this can be + # assumed. + wwn = stdout.split("\n")[0].split('"')[1] + self.assertEqual(logical_disk['root_device_hint']['wwn'], wwn) - manager.delete_configuration() + manager.delete_configuration() + + def test_raid_0_single_drive(self): + self._test_create_configuration_single_logical_drive('0') + + def test_raid_1_single_drive(self): + self._test_create_configuration_single_logical_drive('1') + + def test_raid_5_single_drive(self): + self._test_create_configuration_single_logical_drive('5') + + def test_raid_6_single_drive(self): + self._test_create_configuration_single_logical_drive('6') + + def test_raid_10_single_drive(self): + self._test_create_configuration_single_logical_drive('1+0') + + def test_raid_50_single_drive(self): + self._test_create_configuration_single_logical_drive('5+0') + + def test_raid_60_single_drive(self): + self._test_create_configuration_single_logical_drive('6+0') diff --git a/proliantutils/hpssa/constants.py b/proliantutils/hpssa/constants.py index df121461..c5243662 100644 --- a/proliantutils/hpssa/constants.py +++ b/proliantutils/hpssa/constants.py @@ -30,6 +30,9 @@ RAID_60 = '6+0' RAID_1_ADM = '1ADM' RAID_10_ADM = '10ADM' +RAID_LEVEL_INPUT_TO_HPSSA_MAPPING = {RAID_50: '50', RAID_60: '60'} +RAID_LEVEL_HPSSA_TO_INPUT_MAPPING = { + v: k for k, v in RAID_LEVEL_INPUT_TO_HPSSA_MAPPING.iteritems()} INTERFACE_TYPE_MAP = {'SCSI': INTERFACE_TYPE_SCSI, 'SAS': INTERFACE_TYPE_SAS, @@ -49,7 +52,8 @@ RAID_LEVEL_MIN_DISKS = {RAID_0: 2, RAID_5: 3, RAID_6: 4, RAID_10: 4, - RAID_50: 6} + RAID_50: 6, + RAID_60: 8} def get_interface_type(ssa_interface): diff --git a/proliantutils/hpssa/objects.py b/proliantutils/hpssa/objects.py index 43ed775f..6f085d74 100644 --- a/proliantutils/hpssa/objects.py +++ b/proliantutils/hpssa/objects.py @@ -326,6 +326,11 @@ class Controller(object): phy_drive_ids = ','.join(physical_drive_ids) size_mb = logical_drive_info['size_gb'] * 1024 raid_level = logical_drive_info['raid_level'] + + # For RAID levels (like 5+0 and 6+0), HPSSA names them differently. + # Check if we have mapping stored, otherwise use the same. + raid_level = constants.RAID_LEVEL_INPUT_TO_HPSSA_MAPPING.get( + raid_level, raid_level) self.execute_cmd("create", "type=logicaldrive", "drives=%s" % phy_drive_ids, "raid=%s" % raid_level, @@ -382,7 +387,14 @@ class LogicalDrive(object): # TODO(rameshg87): Check if size is always reported in GB self.size_gb = int(float(self.properties['Size'].rstrip(' GB'))) + self.raid_level = self.properties.get('Fault Tolerance') + # For RAID levels (like 5+0 and 6+0), HPSSA names them differently. + # Check if we have mapping stored, otherwise use the same. + raid_level_mapping = constants.RAID_LEVEL_HPSSA_TO_INPUT_MAPPING + self.raid_level = raid_level_mapping.get(self.raid_level, + self.raid_level) + self.volume_name = self.properties.get('Logical Drive Label') # Trim down the WWN to 16 digits (8 bytes) so that it matches diff --git a/proliantutils/hpssa/raid_config_schema.json b/proliantutils/hpssa/raid_config_schema.json index 5e689aaf..e50c034f 100644 --- a/proliantutils/hpssa/raid_config_schema.json +++ b/proliantutils/hpssa/raid_config_schema.json @@ -9,7 +9,7 @@ "properties": { "raid_level": { "type": "string", - "enum": [ "0", "1", "2", "5", "6", "1+0" ], + "enum": [ "0", "1", "5", "6", "1+0", "5+0", "6+0" ], "description": "RAID level for the logical disk. Required." }, "size_gb": { diff --git a/proliantutils/tests/hpssa/raid_constants.py b/proliantutils/tests/hpssa/raid_constants.py index 242735cb..4d8070ed 100644 --- a/proliantutils/tests/hpssa/raid_constants.py +++ b/proliantutils/tests/hpssa/raid_constants.py @@ -437,6 +437,248 @@ Smart Array P822 in Slot 2 Model: SRCv24x6G ''' + +HPSSA_ONE_DRIVE_RAID_50 = ''' + +Smart Array P822 in Slot 2 + Bus Interface: PCI + Slot: 2 + Serial Number: PDVTF0BRH5T0MO + Cache Serial Number: PBKUD0BRH5T3I6 + RAID 6 (ADG) Status: Enabled + Controller Status: OK + Hardware Revision: B + Firmware Version: 4.68 + Rebuild Priority: Medium + Expand Priority: Medium + Surface Scan Delay: 3 secs + Surface Scan Mode: Idle + Queue Depth: Automatic + Monitor and Performance Delay: 60 min + Elevator Sort: Enabled + Degraded Performance Optimization: Disabled + Inconsistency Repair Policy: Disabled + Wait for Cache Room: Disabled + Surface Analysis Inconsistency Notification: Disabled + Post Prompt Timeout: 15 secs + Cache Board Present: True + Cache Status: OK + Cache Ratio: 10% Read / 90% Write + Drive Write Cache: Disabled + Total Cache Size: 2.0 GB + Total Cache Memory Available: 1.8 GB + No-Battery Write Cache: Disabled + Cache Backup Power Source: Capacitors + Battery/Capacitor Count: 1 + Battery/Capacitor Status: OK + SATA NCQ Supported: True + Spare Activation Mode: Activate on physical drive failure (default) + Controller Temperature (C): 88 + Cache Module Temperature (C): 38 + Capacitor Temperature (C): 23 + Number of Ports: 6 (2 Internal / 4 External ) + Driver Name: hpsa + Driver Version: 3.4.4 + Driver Supports HP SSD Smart Path: True + + Array: A + Interface Type: SAS + Unused Space: 3280165 MB + Status: OK + MultiDomain Status: OK + Array Type: Data + HP SSD Smart Path: disable + + + + Logical Drive: 1 + Size: 100.0 GB + Fault Tolerance: 50 + Number of Parity Groups: 2 + Heads: 255 + Sectors Per Track: 32 + Cylinders: 25700 + Strip Size: 256 KB + Full Stripe Size: 512 KB + Status: OK + MultiDomain Status: OK + Caching: Enabled + Parity Initialization Status: Queued + Unique Identifier: 600508B1001C0FC2145AA6F3A0AF2A57 + Disk Name: /dev/sda + Mount Points: None + Logical Drive Label: 02795E8FPDVTF0BRH5T0MOF6B8 + Parity Group 0: + physicaldrive 5I:1:1 (port 5I:box 1:bay 1, SAS, 600 GB, OK) + physicaldrive 5I:1:3 (port 5I:box 1:bay 3, SAS, 600 GB, OK) + physicaldrive 6I:1:5 (port 6I:box 1:bay 5, SAS, 600 GB, OK) + Parity Group 1: + physicaldrive 5I:1:2 (port 5I:box 1:bay 2, SAS, 600 GB, OK) + physicaldrive 5I:1:4 (port 5I:box 1:bay 4, SAS, 600 GB, OK) + physicaldrive 6I:1:6 (port 6I:box 1:bay 6, SAS, 600 GB, OK) + Drive Type: Data + LD Acceleration Method: Controller Cache + + physicaldrive 5I:1:1 + Port: 5I + Box: 1 + Bay: 1 + Status: OK + Drive Type: Data Drive + Interface Type: SAS + Size: 600 GB + Native Block Size: 512 + Rotational Speed: 15000 + Firmware Revision: HPD6 + Serial Number: 6SL7G55D0000N4173JLT + Model: HP EF0600FARNA + Current Temperature (C): 36 + Maximum Temperature (C): 43 + PHY Count: 2 + PHY Transfer Rate: 6.0Gbps, Unknown + Drive Authentication Status: OK + Carrier Application Version: 11 + Carrier Bootloader Version: 6 + + physicaldrive 5I:1:2 + Port: 5I + Box: 1 + Bay: 2 + Status: OK + Drive Type: Data Drive + Interface Type: SAS + Size: 600 GB + Native Block Size: 512 + Rotational Speed: 15000 + Firmware Revision: HPD6 + Serial Number: 6SL7H2DM0000B41800Y0 + Model: HP EF0600FARNA + Current Temperature (C): 37 + Maximum Temperature (C): 44 + PHY Count: 2 + PHY Transfer Rate: 6.0Gbps, Unknown + Drive Authentication Status: OK + Carrier Application Version: 11 + Carrier Bootloader Version: 6 + + physicaldrive 5I:1:3 + Port: 5I + Box: 1 + Bay: 3 + Status: OK + Drive Type: Data Drive + Interface Type: SAS + Size: 600 GB + Native Block Size: 512 + Rotational Speed: 15000 + Firmware Revision: HPD6 + Serial Number: 6SL7G4ZN0000B41707PD + Model: HP EF0600FARNA + Current Temperature (C): 35 + Maximum Temperature (C): 42 + PHY Count: 2 + PHY Transfer Rate: 6.0Gbps, Unknown + Drive Authentication Status: OK + Carrier Application Version: 11 + Carrier Bootloader Version: 6 + + physicaldrive 5I:1:4 + Port: 5I + Box: 1 + Bay: 4 + Status: OK + Drive Type: Data Drive + Interface Type: SAS + Size: 600 GB + Native Block Size: 512 + Rotational Speed: 15000 + Firmware Revision: HPD6 + Serial Number: 6SL7H27F0000B41800S0 + Model: HP EF0600FARNA + Current Temperature (C): 38 + 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 + + physicaldrive 6I:1:5 + Port: 6I + Box: 1 + Bay: 5 + Status: OK + Drive Type: Data Drive + Interface Type: SAS + Size: 600 GB + Native Block Size: 512 + Rotational Speed: 15000 + Firmware Revision: HPD6 + Serial Number: 6SL7H2BR0000B41800V8 + Model: HP EF0600FARNA + Current Temperature (C): 33 + Maximum Temperature (C): 41 + PHY Count: 2 + PHY Transfer Rate: 6.0Gbps, Unknown + Drive Authentication Status: OK + Carrier Application Version: 11 + Carrier Bootloader Version: 6 + + physicaldrive 6I:1:6 + Port: 6I + Box: 1 + Bay: 6 + Status: OK + Drive Type: Data Drive + Interface Type: SAS + Size: 600 GB + Native Block Size: 512 + Rotational Speed: 15000 + Firmware Revision: HPD6 + Serial Number: 6SL7G4WD0000N4180GEJ + Model: HP EF0600FARNA + Current Temperature (C): 36 + Maximum Temperature (C): 44 + PHY Count: 2 + PHY Transfer Rate: 6.0Gbps, Unknown + Drive Authentication Status: OK + Carrier Application Version: 11 + Carrier Bootloader Version: 6 + + + unassigned + + physicaldrive 6I:1:7 + Port: 6I + Box: 1 + Bay: 7 + Status: OK + Drive Type: Unassigned Drive + Interface Type: SAS + Size: 600 GB + Native Block Size: 512 + Rotational Speed: 15000 + Firmware Revision: HPD6 + Serial Number: 6SL7G54Q0000N4180W34 + Model: HP EF0600FARNA + Current Temperature (C): 33 + Maximum Temperature (C): 39 + PHY Count: 2 + PHY Transfer Rate: 6.0Gbps, Unknown + Drive Authentication Status: OK + Carrier Application Version: 11 + Carrier Bootloader Version: 6 + + + SEP (Vendor ID PMCSIERA, Model SRCv24x6G) 380 + Device Number: 380 + Firmware Version: RevB + WWID: 5001438028842E1F + Vendor ID: PMCSIERA + Model: SRCv24x6G + +''' + HPSSA_ONE_DRIVE_100GB_RAID_5 = ''' Smart Array P822 in Slot 2 diff --git a/proliantutils/tests/hpssa/test_objects.py b/proliantutils/tests/hpssa/test_objects.py index 86878c9e..4ce3aa02 100644 --- a/proliantutils/tests/hpssa/test_objects.py +++ b/proliantutils/tests/hpssa/test_objects.py @@ -97,6 +97,16 @@ class ServerTest(testtools.TestCase): self.assertEqual(controller, physical_drive.parent) self.assertEqual(400, physical_drive.size_gb) + def test_server_object_one_logical_drive_raid_level_mappping( + self, get_all_details_mock): + stdout = raid_constants.HPSSA_ONE_DRIVE_RAID_50 + get_all_details_mock.return_value = stdout + + server = objects.Server() + + logical_drive = server.controllers[0].raid_arrays[0].logical_drives[0] + self.assertEqual(constants.RAID_50, logical_drive.raid_level) + def test_get_controller_by_id(self, get_all_details_mock): get_all_details_mock.return_value = raid_constants.HPSSA_ONE_DRIVE @@ -212,6 +222,35 @@ class ControllerTest(testtools.TestCase): "raid=1", "size=51200") + @mock.patch.object(objects.Controller, 'execute_cmd') + def test_create_logical_drive_raid_level_mapping(self, execute_mock, + get_all_details_mock): + + get_all_details_mock.return_value = raid_constants.HPSSA_NO_DRIVES + + server = objects.Server() + controller = server.controllers[0] + + logical_drive_info = {'size_gb': 50, + 'raid_level': '5+0', + 'volume_name': 'boot_volume', + 'is_boot_volume': 'true', + 'controller': 'Smart Array P822 in Slot 2', + 'physical_disks': ['5I:1:1', + '5I:1:2', + '5I:1:3', + '5I:1:4', + '5I:1:5', + '6I:1:6']} + + controller.create_logical_drive(logical_drive_info, + ['5I:1:1', '5I:1:2', '5I:1:3', + '5I:1:4', '5I:1:5', '6I:1:6']) + execute_mock.assert_called_once_with( + "create", "type=logicaldrive", + "drives=5I:1:1,5I:1:2,5I:1:3,5I:1:4,5I:1:5,6I:1:6", + "raid=50", "size=51200") + @mock.patch.object(objects.Controller, 'execute_cmd') def test_delete_all_logical_drives(self, execute_mock, get_all_details_mock):