DRAC: Drives conversion from JBOD to RAID
Added physical drives conversion from JBOD to RAID mode before RAID create_configuration cleaning step called in iDRAC driver. Change-Id: Ie6d1a9314d1543b73889f6d419541e75b7e06c89 Story: #2006479 Task: #36422
This commit is contained in:
parent
a2ae57c457
commit
8e3f682e29
@ -7,7 +7,7 @@
|
||||
proliantutils>=2.9.1
|
||||
pysnmp>=4.3.0,<5.0.0
|
||||
python-scciclient>=0.8.0
|
||||
python-dracclient>=3.0.0,<4.0.0
|
||||
python-dracclient>=3.1.0,<4.0.0
|
||||
python-xclarityclient>=0.1.6
|
||||
|
||||
# The Redfish hardware type uses the Sushy library
|
||||
|
@ -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.'))
|
||||
]
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,33 @@ 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()
|
||||
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)
|
||||
|
||||
return _commit_to_controllers(
|
||||
node,
|
||||
controllers, substep='completed')
|
||||
|
||||
|
||||
def abandon_config(node, raid_controller):
|
||||
"""Deletes all pending changes on a RAID controller.
|
||||
|
||||
@ -833,18 +898,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 +1005,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 +1035,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(
|
||||
|
@ -284,6 +284,66 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {
|
||||
'is_reboot_required': constants.RebootRequired.optional,
|
||||
'is_commit_required': True}},
|
||||
'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 +806,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 +837,13 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +859,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 +885,27 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +929,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 +940,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 +964,19 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +992,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 +1008,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 +1034,13 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +1062,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 +1079,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 +1105,13 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +1131,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 +1148,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 +1166,15 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +1221,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 +1229,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 +1254,14 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +1298,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 +1306,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 +1330,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']
|
||||
mock_change_physical_disk_state.return_value = {
|
||||
'is_reboot_required': constants.RebootRequired.optional,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +1368,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 +1376,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 +1406,13 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +1450,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 +1487,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 +1512,12 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +1549,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 +1606,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 +1635,13 @@ 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,
|
||||
'conversion_results': {
|
||||
'RAID.Integrated.1-1': {'is_reboot_required': 'optional',
|
||||
'is_commit_required': True}},
|
||||
'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 +1674,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,
|
||||
|
@ -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 = (
|
||||
|
@ -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
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Hardware type ``idrac`` converts physical drives from
|
||||
``JBOD`` to ``RAID`` mode before building RAID on them.
|
Loading…
x
Reference in New Issue
Block a user