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)
Example #3
0
    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)
Example #4
0
    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']))
Example #7
0
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
Example #8
0
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