Browse Source

Merge "DRAC: Drives conversion from JBOD to RAID" into stable/train

tags/13.0.6
Zuul 1 month ago
committed by Gerrit Code Review
parent
commit
a5ca82e362
7 changed files with 356 additions and 49 deletions
  1. +7
    -1
      ironic/conf/drac.py
  2. +27
    -1
      ironic/drivers/modules/drac/job.py
  3. +110
    -5
      ironic/drivers/modules/drac/raid.py
  4. +197
    -41
      ironic/tests/unit/drivers/modules/drac/test_raid.py
  5. +6
    -1
      ironic/tests/unit/drivers/third_party_driver_mock_specs.py
  6. +4
    -0
      ironic/tests/unit/drivers/third_party_driver_mocks.py
  7. +5
    -0
      releasenotes/notes/idrac-drives-conversion-jbod-to-raid-1a229627708e10b9.yaml

+ 7
- 1
ironic/conf/drac.py View File

@@ -28,7 +28,13 @@ opts = [
help=_('Maximum amount of time (in seconds) to wait for '
'the boot device configuration job to transition '
'to the correct state to allow a reboot or power '
'on to complete.'))
'on to complete.')),
cfg.IntOpt('config_job_max_retries',
default=240,
min=1,
help=_('Maximum number of retries for '
'the configuration job to complete '
'successfully.'))
]




+ 27
- 1
ironic/drivers/modules/drac/job.py View File

@@ -17,21 +17,23 @@ DRAC Lifecycle job specific methods

from oslo_log import log as logging
from oslo_utils import importutils
import retrying

from ironic.common import exception
from ironic.common.i18n import _
from ironic.conf import CONF
from ironic.drivers.modules.drac import common as drac_common

drac_exceptions = importutils.try_import('dracclient.exceptions')

LOG = logging.getLogger(__name__)
WAIT_CLOCK = 5


def validate_job_queue(node, name_prefix=None):
"""Validates the job queue on the node.

It raises an exception if an unfinished configuration job exists.

:param node: an ironic node object.
:param name_prefix: A name prefix for jobs to validate.
:raises: DracOperationError on an error from python-dracclient.
@@ -86,3 +88,27 @@ def list_unfinished_jobs(node):
{'node_uuid': node.uuid,
'error': exc})
raise exception.DracOperationError(error=exc)


@retrying.retry(
retry_on_exception=lambda e: isinstance(e, exception.DracOperationError),
stop_max_attempt_number=CONF.drac.config_job_max_retries,
wait_fixed=WAIT_CLOCK * 1000)
def wait_for_job_completion(node,
retries=CONF.drac.config_job_max_retries):
"""Wait for job to complete

It will wait for the job to complete for 20 minutes and raises timeout
if job never complete within given interval of time.
:param node: an ironic node object.
:param retries: no of retries to make conductor wait.
:raises: DracOperationError on exception raised from python-dracclient
or a timeout while waiting for job completion.
"""
if not list_unfinished_jobs(node):
return
err_msg = _(
'There are unfinished jobs in the job '
'queue on node %(node_uuid)r ') % {'node_uuid': node.uuid}
LOG.warning(err_msg)
raise exception.DracOperationError(error=err_msg)

+ 110
- 5
ironic/drivers/modules/drac/raid.py View File

@@ -15,6 +15,7 @@
DRAC RAID specific methods
"""

from collections import defaultdict
import math

from futurist import periodics
@@ -309,6 +310,43 @@ def clear_foreign_config(node, raid_controller):
raise exception.DracOperationError(error=exc)


def change_physical_disk_state(node, mode=None,
controllers_to_physical_disk_ids=None):
"""Convert disks RAID status

This method converts the requested physical disks from
RAID to JBOD or vice versa. It does this by only converting the
disks that are not already in the correct state.

:param node: an ironic node object.
:param mode: the mode to change the disks either to RAID or JBOD.
:param controllers_to_physical_disk_ids: Dictionary of controllers and
corresponding disk ids to convert to the requested mode.
:return: a dictionary containing:
- conversion_results, a dictionary that maps controller ids
to the conversion results for that controller.
The conversion results are a dict that contains:
- The is_commit_required key with the value always set to
True indicating that a config job must be created to
complete disk conversion.
- The is_reboot_required key with a RebootRequired
enumerated value indicating whether the server must be
rebooted to complete disk conversion.
:raises: DRACOperationError on an error from python-dracclient.
"""
try:
drac_job.validate_job_queue(node)
client = drac_common.get_drac_client(node)
return client.change_physical_disk_state(
mode, controllers_to_physical_disk_ids)
except drac_exceptions.BaseClientException as exc:
LOG.error('DRAC driver failed to change physical drives '
'to %(mode)s mode for node %(node_uuid)s. '
'Reason: %(error)s.',
{'mode': mode, 'node_uuid': node.uuid, 'error': exc})
raise exception.DracOperationError(error=exc)


def commit_config(node, raid_controller, reboot=False, realtime=False):
"""Apply all pending changes on a RAID controller.

@@ -338,6 +376,42 @@ def commit_config(node, raid_controller, reboot=False, realtime=False):
raise exception.DracOperationError(error=exc)


def _change_physical_disk_mode(node, mode=None,
controllers_to_physical_disk_ids=None):
"""Physical drives conversion from RAID to JBOD or vice-versa.

:param node: an ironic node object.
:param mode: the mode to change the disks either to RAID or JBOD.
:param controllers_to_physical_disk_ids: Dictionary of controllers and
corresponding disk ids to convert to the requested mode.
:returns: states.CLEANWAIT if deletion is in progress asynchronously
or None if it is completed.
"""
change_disk_state = change_physical_disk_state(
node, mode, controllers_to_physical_disk_ids)

controllers = list()
if 'conversion_results' in change_disk_state:
conversion_results = change_disk_state['conversion_results']
for controller_id, result in conversion_results.items():
controller = {'raid_controller': controller_id,
'is_reboot_required': result['is_reboot_required'],
'is_commit_required': result['is_commit_required']}
controllers.append(controller)
else:
controller_ids = change_disk_state['commit_required_ids']
for controller_id in controller_ids:
controller = {'raid_controller': controller_id,
'is_reboot_required':
change_disk_state['is_reboot_required'],
'is_commit_required': True}
controllers.append(controller)

return _commit_to_controllers(
node,
controllers, substep='completed')


def abandon_config(node, raid_controller):
"""Deletes all pending changes on a RAID controller.

@@ -833,18 +907,18 @@ def _commit_to_controllers(node, controllers, substep="completed"):
else:
for controller in controllers:
mix_controller = controller['raid_controller']
reboot = True if controller == controllers[-1] else False
reboot = (controller == controllers[-1])
job_details = _create_config_job(
node, controller=mix_controller,
reboot=reboot, realtime=False,
raid_config_job_ids=raid_config_job_ids,
raid_config_parameters=raid_config_parameters)

driver_internal_info['raid_config_job_ids'] = job_details[
'raid_config_job_ids']
driver_internal_info['raid_config_job_ids'].extend(job_details[
'raid_config_job_ids'])

driver_internal_info['raid_config_parameters'] = job_details[
'raid_config_parameters']
driver_internal_info['raid_config_parameters'].extend(job_details[
'raid_config_parameters'])

node.driver_internal_info = driver_internal_info

@@ -940,6 +1014,7 @@ class DracWSManRAID(base.RAIDInterface):
node = task.node

logical_disks = node.target_raid_config['logical_disks']

for disk in logical_disks:
if disk['size_gb'] == 'MAX' and 'physical_disks' not in disk:
raise exception.InvalidParameterValue(
@@ -969,6 +1044,36 @@ class DracWSManRAID(base.RAIDInterface):
logical_disks_to_create = _filter_logical_disks(
logical_disks, create_root_volume, create_nonroot_volumes)

controllers_to_physical_disk_ids = defaultdict(list)
for logical_disk in logical_disks_to_create:
# Not applicable to JBOD logical disks.
if logical_disk['raid_level'] == 'JBOD':
continue

for physical_disk_name in logical_disk['physical_disks']:
controllers_to_physical_disk_ids[
logical_disk['controller']].append(
physical_disk_name)

if logical_disks_to_create:
LOG.debug(
"Converting physical disks configured to back RAID "
"logical disks to RAID mode for node %(node_uuid)s ",
{"node_uuid": node.uuid})
raid = drac_constants.RaidStatus.raid
_change_physical_disk_mode(
node, raid, controllers_to_physical_disk_ids)

LOG.debug("Waiting for physical disk conversion to complete "
"for node %(node_uuid)s. ", {"node_uuid": node.uuid})
drac_job.wait_for_job_completion(node)

LOG.info(
"Completed converting physical disks configured to back RAID "
"logical disks to RAID mode for node %(node_uuid)s",
{'node_uuid': node.uuid})

controllers = list()
for logical_disk in logical_disks_to_create:
controller = dict()
controller_cap = create_virtual_disk(


+ 197
- 41
ironic/tests/unit/drivers/modules/drac/test_raid.py View File

@@ -284,6 +284,59 @@ class DracManageVirtualDisksTestCase(test_utils.BaseDracTest):
exception.DracOperationError, drac_raid.clear_foreign_config,
self.node, 'RAID.Integrated.1-1')

@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
autospec=True)
def test_change_physical_disk_state(self,
mock_validate_job_queue,
mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client
controllers_to_physical_disk_ids = {'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']}
expected_change_disk_state = {
'is_reboot_required': True,
'commit_required_ids': ['RAID.Integrated.1-1']}
mode = constants.RaidStatus.raid
mock_client.change_physical_disk_state.return_value = \
expected_change_disk_state
actual_change_disk_state = drac_raid.change_physical_disk_state(
self.node,
mode=mode,
controllers_to_physical_disk_ids=controllers_to_physical_disk_ids)

mock_validate_job_queue.assert_called_once_with(self.node)
mock_client.change_physical_disk_state.assert_called_once_with(
mode, controllers_to_physical_disk_ids)
self.assertEqual(expected_change_disk_state, actual_change_disk_state)

@mock.patch.object(drac_raid, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
autospec=True)
def test__change_physical_disk_mode(self,
mock_commit_config,
mock_change_physical_disk_state,
mock_get_drac_client):
mock_commit_config.return_value = '42'
mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}

actual_change_disk_state = drac_raid._change_physical_disk_mode(
self.node, mode=constants.RaidStatus.raid)
self.assertEqual(['42'],
self.node.driver_internal_info['raid_config_job_ids'])
self.assertEqual('completed',
self.node.driver_internal_info['raid_config_substep'])
self.assertEqual(
['RAID.Integrated.1-1'],
self.node.driver_internal_info['raid_config_parameters'])
mock_commit_config.assert_called_once_with(
self.node, raid_controller='RAID.Integrated.1-1', reboot=False,
realtime=True)
self.assertEqual(states.DEPLOYWAIT, actual_change_disk_state)

def test_commit_config(self, mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client
@@ -746,12 +799,17 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@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, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', spec_set=True,
autospec=True)
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
autospec=True)
def _test_create_configuration(
self, expected_state, mock_commit_config, mock_validate_job_queue,
mock_list_physical_disks, mock__reset_raid_config,
mock_get_drac_client):
self, expected_state, mock_commit_config,
mock_wait_for_job_completion, mock_change_physical_disk_state,
mock_validate_job_queue, mock_list_physical_disks,
mock__reset_raid_config, mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client
physical_disks = self._generate_physical_disks()
@@ -772,6 +830,10 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
mock__reset_raid_config.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True}
mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}
mock_commit_config.side_effect = ['42', '12']
mock_client.create_virtual_disk.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True}
@@ -787,13 +849,17 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1'],
'1', 51200, None, 2, 1)

mock_commit_config.assert_called_once_with(
mock_commit_config.assert_called_with(
task.node, raid_controller='RAID.Integrated.1-1', reboot=False,
realtime=True)

self.assertEqual(expected_state, return_value)
self.assertEqual(2, mock_commit_config.call_count)
self.assertEqual(1, mock_client.create_virtual_disk.call_count)
self.assertEqual(1, mock_change_physical_disk_state.call_count)

self.node.refresh()
self.assertEqual(['42'],
self.assertEqual(['42', '12'],
self.node.driver_internal_info['raid_config_job_ids'])

def test_create_configuration_in_clean(self):
@@ -809,16 +875,24 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@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, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', spec_set=True,
autospec=True)
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
autospec=True)
def test_create_configuration_no_change(
self, mock_commit_config, mock_validate_job_queue,
mock_list_physical_disks,
mock_get_drac_client):
self, mock_commit_config, mock_wait_for_job_completion,
mock_change_physical_disk_state, mock_validate_job_queue,
mock_list_physical_disks, mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client
physical_disks = self._generate_physical_disks()
mock_list_physical_disks.return_value = physical_disks
mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}
mock_commit_config.return_value = '42'
mock_client.create_virtual_disk.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True}
@@ -842,6 +916,10 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@mock.patch.object(drac_raid, '_reset_raid_config', autospec=True)
@mock.patch.object(drac_raid, 'list_virtual_disks', autospec=True)
@mock.patch.object(drac_raid, 'list_physical_disks', autospec=True)
@mock.patch.object(drac_raid, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', spec_set=True,
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,
@@ -849,6 +927,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
def test_create_configuration_delete_existing(
self, mock_commit_config,
mock_validate_job_queue,
mock_wait_for_job_completion,
mock_change_physical_disk_state,
mock_list_physical_disks,
mock_list_virtual_disks,
mock__reset_raid_config,
@@ -871,12 +951,16 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
raid_controller = test_utils.make_raid_controller(
raid_controller_dict)
mock_list_physical_disks.return_value = physical_disks
mock_commit_config.return_value = '42'
mock_commit_config.side_effect = ['42', '12']
mock_client.list_raid_controllers.return_value = [raid_controller]
mock__reset_raid_config.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True}

mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}

mock_client.create_virtual_disk.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True
@@ -892,15 +976,15 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
['Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1',
'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1'],
'1', 51200, None, 2, 1)
mock_commit_config.assert_called_once_with(
mock_commit_config.assert_called_with(
task.node, raid_controller='RAID.Integrated.1-1',
realtime=True, reboot=False)

self.assertEqual(1, mock_commit_config.call_count)
self.assertEqual(2, mock_commit_config.call_count)

self.assertEqual(states.DEPLOYWAIT, return_value)
self.node.refresh()
self.assertEqual(['42'],
self.assertEqual(['42', '12'],
self.node.driver_internal_info['raid_config_job_ids'])

@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
@@ -908,10 +992,15 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@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, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', spec_set=True,
autospec=True)
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
autospec=True)
def test_create_configuration_with_nested_raid_level(
self, mock_commit_config, mock_validate_job_queue,
self, mock_commit_config, mock_wait_for_job_completion,
mock_change_physical_disk_state, mock_validate_job_queue,
mock_list_physical_disks, mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client
@@ -929,7 +1018,10 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):

physical_disks = self._generate_physical_disks()
mock_list_physical_disks.return_value = physical_disks
mock_commit_config.return_value = '42'
mock_commit_config.side_effect = ['42', '12']
mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}
mock_client.create_virtual_disk.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True}
@@ -951,12 +1043,16 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
'5+0', 102400, None, 3, 2)

# Commits to the controller
mock_commit_config.assert_called_once_with(
mock_commit_config.assert_called_with(
mock.ANY, raid_controller='RAID.Integrated.1-1', reboot=False,
realtime=True)

self.assertEqual(2, mock_commit_config.call_count)
self.assertEqual(1, mock_client.create_virtual_disk.call_count)
self.assertEqual(1, mock_change_physical_disk_state.call_count)

self.node.refresh()
self.assertEqual(['42'],
self.assertEqual(['42', '12'],
self.node.driver_internal_info['raid_config_job_ids'])

@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
@@ -964,12 +1060,16 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@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, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', 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):
self, mock_commit_config, mock_wait_for_job_completion,
mock_change_physical_disk_state, mock_validate_job_queue,
mock_list_physical_disks, mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client

@@ -986,7 +1086,10 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
physical_disks = self._generate_physical_disks()
mock_list_physical_disks.return_value = physical_disks

mock_commit_config.return_value = '42'
mock_commit_config.side_effect = ['42', '12']
mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}
mock_client.create_virtual_disk.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True}
@@ -1006,12 +1109,16 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
'1+0', 102400, None, None, None)

# Commits to the controller
mock_commit_config.assert_called_once_with(
mock_commit_config.assert_called_with(
mock.ANY, raid_controller='RAID.Integrated.1-1', reboot=False,
realtime=True)

self.assertEqual(2, mock_commit_config.call_count)
self.assertEqual(1, mock_client.create_virtual_disk.call_count)
self.assertEqual(1, mock_change_physical_disk_state.call_count)

self.node.refresh()
self.assertEqual(['42'],
self.assertEqual(['42', '12'],
self.node.driver_internal_info['raid_config_job_ids'])

@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
@@ -1019,10 +1126,15 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@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, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', spec_set=True,
autospec=True)
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
autospec=True)
def test_create_configuration_with_multiple_controllers(
self, mock_commit_config, mock_validate_job_queue,
self, mock_commit_config, mock_wait_for_job_completion,
mock_change_physical_disk_state, mock_validate_job_queue,
mock_list_physical_disks, mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client
@@ -1032,7 +1144,12 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
physical_disks = self._generate_physical_disks()
mock_list_physical_disks.return_value = physical_disks

mock_commit_config.side_effect = ['42', '12', '13']
mock_commit_config.side_effect = ['42', '12', '13', '14']

mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}

mock_client.create_virtual_disk.side_effect = [{
'is_reboot_required': constants.RebootRequired.true,
'is_commit_required': True
@@ -1079,7 +1196,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
any_order=True)

self.node.refresh()
self.assertEqual(['42', '12', '13'],
self.assertEqual(['42', '12', '13', '14'],
self.node.driver_internal_info['raid_config_job_ids'])

@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
@@ -1087,10 +1204,15 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@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, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', spec_set=True,
autospec=True)
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
autospec=True)
def test_create_configuration_with_backing_physical_disks(
self, mock_commit_config, mock_validate_job_queue,
self, mock_commit_config, mock_wait_for_job_completion,
mock_change_physical_disk_state, mock_validate_job_queue,
mock_list_physical_disks, mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client
@@ -1107,7 +1229,11 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
physical_disks = self._generate_physical_disks()
mock_list_physical_disks.return_value = physical_disks

mock_commit_config.side_effect = ['42', '12', '13']
mock_commit_config.side_effect = ['42', '12']
mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}

mock_client.create_virtual_disk.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True
@@ -1144,7 +1270,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
reboot=False, realtime=True)

self.node.refresh()
self.assertEqual(['42'],
self.assertEqual(['42', '12'],
self.node.driver_internal_info['raid_config_job_ids'])

@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
@@ -1152,12 +1278,16 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@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, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', spec_set=True,
autospec=True)
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
autospec=True)
def test_create_configuration_with_predefined_number_of_phyisical_disks(
self, mock_commit_config, mock_validate_job_queue,
self, mock_commit_config, mock_wait_for_job_completion,
mock_change_physical_disk_state, mock_validate_job_queue,
mock_list_physical_disks, mock_get_drac_client):

mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client

@@ -1172,6 +1302,9 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
physical_disks = self._generate_physical_disks()
mock_list_physical_disks.return_value = physical_disks
mock_commit_config.side_effect = ['42', '12']
mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}
mock_client.create_virtual_disk.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True
@@ -1204,7 +1337,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
reboot=False, realtime=True)

self.node.refresh()
self.assertEqual(['42'],
self.assertEqual(['42', '12'],
self.node.driver_internal_info['raid_config_job_ids'])

@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
@@ -1212,10 +1345,15 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@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, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', spec_set=True,
autospec=True)
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
autospec=True)
def test_create_configuration_with_max_size(
self, mock_commit_config, mock_validate_job_queue,
self, mock_commit_config, mock_wait_for_job_completion,
mock_change_physical_disk_state, mock_validate_job_queue,
mock_list_physical_disks, mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client
@@ -1237,7 +1375,10 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
physical_disks = self._generate_physical_disks()
mock_list_physical_disks.return_value = physical_disks

mock_commit_config.side_effect = ['42', '12', '13']
mock_commit_config.side_effect = ['42', '12']
mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}
mock_client.create_virtual_disk.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True
@@ -1275,7 +1416,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
realtime=True)

self.node.refresh()
self.assertEqual(['42'],
self.assertEqual(['42', '12'],
self.node.driver_internal_info['raid_config_job_ids'])

@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
@@ -1312,10 +1453,15 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@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, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', spec_set=True,
autospec=True)
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
autospec=True)
def test_create_configuration_with_share_physical_disks(
self, mock_commit_config, mock_validate_job_queue,
self, mock_commit_config, mock_wait_for_job_completion,
mock_change_physical_disk_state, mock_validate_job_queue,
mock_list_physical_disks, mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client
@@ -1332,6 +1478,9 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
mock_list_physical_disks.return_value = physical_disks

mock_commit_config.side_effect = ['42', '12']
mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}
mock_client.create_virtual_disk.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True
@@ -1363,7 +1512,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
realtime=True)

self.node.refresh()
self.assertEqual(['42'],
self.assertEqual(['42', '12'],
self.node.driver_internal_info['raid_config_job_ids'])

@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
@@ -1420,12 +1569,16 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
@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, 'change_physical_disk_state', spec_set=True,
autospec=True)
@mock.patch.object(drac_job, 'wait_for_job_completion', spec_set=True,
autospec=True)
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
autospec=True)
def test_create_configuration_with_max_size_and_share_physical_disks(
self, mock_commit_config, mock_validate_job_queue,
mock_list_physical_disks,
mock_get_drac_client):
self, mock_commit_config, mock_wait_for_job_completion,
mock_change_physical_disk_state, mock_validate_job_queue,
mock_list_physical_disks, mock_get_drac_client):
mock_client = mock.Mock()
mock_get_drac_client.return_value = mock_client

@@ -1445,7 +1598,10 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
physical_disks = self._generate_physical_disks()
mock_list_physical_disks.return_value = physical_disks

mock_commit_config.return_value = '42'
mock_commit_config.side_effect = ['42', '12']
mock_change_physical_disk_state.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'commit_required_ids': ['RAID.Integrated.1-1']}
mock_client.create_virtual_disk.return_value = {
'is_reboot_required': constants.RebootRequired.optional,
'is_commit_required': True
@@ -1478,7 +1634,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
realtime=True)

self.node.refresh()
self.assertEqual(['42'],
self.assertEqual(['42', '12'],
self.node.driver_internal_info['raid_config_job_ids'])

@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,


+ 6
- 1
ironic/tests/unit/drivers/third_party_driver_mock_specs.py View File

@@ -31,7 +31,8 @@ DRACCLIENT_CONSTANTS_MOD_SPEC = (
'POWER_OFF',
'POWER_ON',
'REBOOT',
'RebootRequired'
'RebootRequired',
'RaidStatus'
)

DRACCLIENT_CONSTANTS_REBOOT_REQUIRED_MOD_SPEC = (
@@ -40,6 +41,10 @@ DRACCLIENT_CONSTANTS_REBOOT_REQUIRED_MOD_SPEC = (
'false'
)

DRACCLIENT_CONSTANTS_RAID_STATUS_MOD_SPEC = (
'jbod',
'raid'
)

# proliantutils
PROLIANTUTILS_SPEC = (


+ 4
- 0
ironic/tests/unit/drivers/third_party_driver_mocks.py View File

@@ -95,6 +95,10 @@ if not dracclient:
true=mock.sentinel.true,
optional=mock.sentinel.optional,
false=mock.sentinel.false)
dracclient.constants.RaidStatus = mock.MagicMock(
spec_set=mock_specs.DRACCLIENT_CONSTANTS_RAID_STATUS_MOD_SPEC,
jbod=mock.sentinel.jbod,
raid=mock.sentinel.raid)

sys.modules['dracclient'] = dracclient
sys.modules['dracclient.client'] = dracclient.client


+ 5
- 0
releasenotes/notes/idrac-drives-conversion-jbod-to-raid-1a229627708e10b9.yaml View File

@@ -0,0 +1,5 @@
---
fixes:
- |
Hardware type ``idrac`` converts physical drives from
``JBOD`` to ``RAID`` mode before building RAID on them.

Loading…
Cancel
Save