def test_allocate_disks_share_physical_disks(self, execute_mock, get_all_details_mock): get_all_details_mock.return_value = raid_constants.ONE_DRIVE_RAID_1 execute_mock.return_value = ( raid_constants.DRIVE_2_RAID_1_OKAY_TO_SHARE, None) rdh = {'wwn': '0x600508b1001c02bd'} controller = 'Smart Array P822 in Slot 2' physical_disks = ['5I:1:1', '5I:1:2'] raid_config = {'logical_disks': [{'size_gb': 50, 'raid_level': '1', 'share_physical_disks': True, 'root_device_hint': rdh, 'controller': controller, 'physical_disks': physical_disks}, {'size_gb': 50, 'raid_level': '1', 'share_physical_disks': True}]} logical_disk = raid_config['logical_disks'][1] server = objects.Server() disk_allocator.allocate_disks(logical_disk, server, raid_config) self.assertEqual(controller, logical_disk['controller']) self.assertEqual('A', logical_disk['array']) self.assertNotIn('physical_disks', logical_disk)
def test_allocate_disks_share_physical_disks(self, execute_mock, get_all_details_mock): get_all_details_mock.return_value = raid_constants.ONE_DRIVE_RAID_1 execute_mock.return_value = (raid_constants.DRIVE_2_RAID_1_OKAY_TO_SHARE, None) rdh = {"wwn": "0x600508b1001c02bd"} controller = "Smart Array P822 in Slot 2" physical_disks = ["5I:1:1", "5I:1:2"] raid_config = { "logical_disks": [ { "size_gb": 50, "raid_level": "1", "share_physical_disks": True, "root_device_hint": rdh, "controller": controller, "physical_disks": physical_disks, }, {"size_gb": 50, "raid_level": "1", "share_physical_disks": True}, ] } logical_disk = raid_config["logical_disks"][1] server = objects.Server() disk_allocator.allocate_disks(logical_disk, server, raid_config) self.assertEqual(controller, logical_disk["controller"]) self.assertEqual("A", logical_disk["array"]) self.assertNotIn("physical_disks", logical_disk)
def test_allocate_disks_share_physical_disks(self, execute_mock, get_all_details_mock): get_all_details_mock.return_value = raid_constants.ONE_DRIVE_RAID_1 execute_mock.return_value = ( raid_constants.DRIVE_2_RAID_1_OKAY_TO_SHARE, None) rdh = {'wwn': '0x600508b1001c02bd'} controller = 'Smart Array P822 in Slot 2' physical_disks = ['5I:1:1', '5I:1:2'] raid_config = { 'logical_disks': [{ 'size_gb': 50, 'raid_level': '1', 'share_physical_disks': True, 'root_device_hint': rdh, 'controller': controller, 'physical_disks': physical_disks }, { 'size_gb': 50, 'raid_level': '1', 'share_physical_disks': True }] } logical_disk = raid_config['logical_disks'][1] server = objects.Server() disk_allocator.allocate_disks(logical_disk, server, raid_config) self.assertEqual(controller, logical_disk['controller']) self.assertEqual('A', logical_disk['array']) self.assertNotIn('physical_disks', logical_disk)
def test_allocate_disks_max_okay(self, get_all_details_mock): get_all_details_mock.return_value = raid_constants.HPSSA_ONE_DRIVE server = objects.Server() logical_disk = { 'size_gb': 'MAX', 'raid_level': '1', 'disk_type': 'hdd', 'interface_type': 'sas' } # Decrease size of three disks so that the remaining gets # selected. disk1 = server.controllers[0].get_physical_drive_by_id('5I:1:3') disk2 = server.controllers[0].get_physical_drive_by_id('6I:1:7') disk3 = server.controllers[0].get_physical_drive_by_id('5I:1:4') disk1.size_gb = 300 disk2.size_gb = 300 disk3.size_gb = 300 raid_config = {'logical_disks': [logical_disk]} disk_allocator.allocate_disks(logical_disk, server, raid_config) self.assertEqual('Smart Array P822 in Slot 2', logical_disk['controller']) self.assertEqual(sorted(['6I:1:5', '6I:1:6']), sorted(logical_disk['physical_disks']))
def test_allocate_disks_okay(self, get_all_details_mock): get_all_details_mock.return_value = raid_constants.HPSSA_ONE_DRIVE server = objects.Server() logical_disk = {"size_gb": 100, "raid_level": "1", "disk_type": "hdd", "interface_type": "sas"} # Decrease size of two disks so that they get selected. disk1 = server.controllers[0].get_physical_drive_by_id("5I:1:3") disk2 = server.controllers[0].get_physical_drive_by_id("6I:1:7") disk1.size_gb = 300 disk2.size_gb = 300 raid_config = {"logical_disks": [logical_disk]} disk_allocator.allocate_disks(logical_disk, server, raid_config) self.assertEqual("Smart Array P822 in Slot 2", logical_disk["controller"]) self.assertEqual(sorted(["5I:1:3", "6I:1:7"]), sorted(logical_disk["physical_disks"]))
def test_allocate_disks_okay(self, get_all_details_mock): get_all_details_mock.return_value = raid_constants.HPSSA_ONE_DRIVE server = objects.Server() logical_disk = {'size_gb': 100, 'raid_level': '1', 'disk_type': 'hdd', 'interface_type': 'sas'} # Decrease size of two disks so that they get selected. disk1 = server.controllers[0].get_physical_drive_by_id('5I:1:3') disk2 = server.controllers[0].get_physical_drive_by_id('6I:1:7') disk1.size_gb = 300 disk2.size_gb = 300 raid_config = {'logical_disks': [logical_disk]} disk_allocator.allocate_disks(logical_disk, server, raid_config) self.assertEqual('Smart Array P822 in Slot 2', logical_disk['controller']) self.assertEqual(sorted(['5I:1:3', '6I:1:7']), sorted(logical_disk['physical_disks']))
def create_configuration(raid_config): """Create a RAID configuration on this server. This method creates the given RAID configuration on the server based on the input passed. :param raid_config: The dictionary containing the requested RAID configuration. This data structure should be as follows: raid_config = {'logical_disks': [{'raid_level': 1, 'size_gb': 100}, <info-for-logical-disk-2> ]} :returns: the current raid configuration. This is same as raid_config with some extra properties like root_device_hint, volume_name, controller, physical_disks, etc filled for each logical disk after its creation. :raises exception.InvalidInputError, if input is invalid. """ validate(raid_config) server = objects.Server() # 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: # - two logical disks - LD1(50), LD(100) # - have 4 physical disks - PD1(50), PD2(50), PD3(100), PD4(100) # # In this case, for RAID1 configuration, if we were to consider # LD1 first and allocate PD3 and PD4 for it, then allocation would # fail. So follow a particular order for allocation. # # Also make sure we create the MAX logical_disks the last to make sure # we allot only the remaining space available. logical_disks_sorted = ( sorted((x for x in raid_config['logical_disks'] if x['size_gb'] != "MAX"), reverse=True, key=lambda x: x['size_gb']) + [x for x in raid_config['logical_disks'] if x['size_gb'] == "MAX"]) # We figure out the new disk created by recording the wwns # before and after the create, and then figuring out the # newly found wwn from it. wwns_before_create = set([x.wwn for x in server.get_logical_drives()]) for logical_disk in logical_disks_sorted: if 'physical_disks' not in logical_disk: disk_allocator.allocate_disks(logical_disk, server, raid_config) controller_id = logical_disk['controller'] controller = server.get_controller_by_id(controller_id) if not controller: msg = ("Unable to find controller named '%s'" % controller_id) raise exception.InvalidInputError(reason=msg) if 'physical_disks' in logical_disk: for physical_disk in logical_disk['physical_disks']: disk_obj = controller.get_physical_drive_by_id(physical_disk) if not disk_obj: msg = ("Unable to find physical disk '%(physical_disk)s' " "on '%(controller)s'" % {'physical_disk': physical_disk, 'controller': controller_id}) raise exception.InvalidInputError(msg) controller.create_logical_drive(logical_disk) # Now find the new logical drive created. server.refresh() wwns_after_create = set([x.wwn for x in server.get_logical_drives()]) new_wwn = wwns_after_create - wwns_before_create if not new_wwn: reason = ("Newly created logical disk with raid_level " "'%(raid_level)s' and size %(size_gb)s GB not " "found." % {'raid_level': logical_disk['raid_level'], 'size_gb': logical_disk['size_gb']}) raise exception.HPSSAOperationError(reason=reason) new_logical_disk = server.get_logical_drive_by_wwn(new_wwn.pop()) new_log_drive_properties = new_logical_disk.get_logical_drive_dict() logical_disk.update(new_log_drive_properties) wwns_before_create = wwns_after_create.copy() _update_physical_disk_details(raid_config, server) return raid_config
def create_configuration(raid_config): """Create a RAID configuration on this server. This method creates the given RAID configuration on the server based on the input passed. :param raid_config: The dictionary containing the requested RAID configuration. This data structure should be as follows: raid_config = {'logical_disks': [{'raid_level': 1, 'size_gb': 100}, <info-for-logical-disk-2> ]} :returns: the current raid configuration. This is same as raid_config with some extra properties like root_device_hint, volume_name, 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. """ server = objects.Server() select_controllers = lambda x: not x.properties.get( 'HBA Mode Enabled', False) _select_controllers_by(server, select_controllers, 'RAID enabled') 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: # - two logical disks - LD1(50), LD(100) # - have 4 physical disks - PD1(50), PD2(50), PD3(100), PD4(100) # # In this case, for RAID1 configuration, if we were to consider # LD1 first and allocate PD3 and PD4 for it, then allocation would # fail. So follow a particular order for allocation. # # Also make sure we create the MAX logical_disks the last to make sure # we allot only the remaining space available. logical_disks_sorted = ( sorted( (x for x in raid_config['logical_disks'] if x['size_gb'] != "MAX"), reverse=True, key=lambda x: x['size_gb']) + [x for x in raid_config['logical_disks'] if x['size_gb'] == "MAX"]) if any(logical_disk['share_physical_disks'] for logical_disk in logical_disks_sorted if 'share_physical_disks' in logical_disk): logical_disks_sorted = _sort_shared_logical_disks(logical_disks_sorted) # We figure out the new disk created by recording the wwns # before and after the create, and then figuring out the # newly found wwn from it. wwns_before_create = set([x.wwn for x in server.get_logical_drives()]) for logical_disk in logical_disks_sorted: if 'physical_disks' not in logical_disk: disk_allocator.allocate_disks(logical_disk, server, raid_config) controller_id = logical_disk['controller'] controller = server.get_controller_by_id(controller_id) if not controller: msg = ( "Unable to find controller named '%(controller)s'." " The available controllers are '%(ctrl_list)s'." % { 'controller': controller_id, 'ctrl_list': ', '.join([c.id for c in server.controllers]) }) raise exception.InvalidInputError(reason=msg) if 'physical_disks' in logical_disk: for physical_disk in logical_disk['physical_disks']: disk_obj = controller.get_physical_drive_by_id(physical_disk) if not disk_obj: msg = ("Unable to find physical disk '%(physical_disk)s' " "on '%(controller)s'" % { 'physical_disk': physical_disk, 'controller': controller_id }) raise exception.InvalidInputError(msg) controller.create_logical_drive(logical_disk) # Now find the new logical drive created. server.refresh() wwns_after_create = set([x.wwn for x in server.get_logical_drives()]) new_wwn = wwns_after_create - wwns_before_create if not new_wwn: reason = ("Newly created logical disk with raid_level " "'%(raid_level)s' and size %(size_gb)s GB not " "found." % { 'raid_level': logical_disk['raid_level'], 'size_gb': logical_disk['size_gb'] }) raise exception.HPSSAOperationError(reason=reason) new_logical_disk = server.get_logical_drive_by_wwn(new_wwn.pop()) new_log_drive_properties = new_logical_disk.get_logical_drive_dict() logical_disk.update(new_log_drive_properties) wwns_before_create = wwns_after_create.copy() _update_physical_disk_details(raid_config, server) return raid_config