summaryrefslogtreecommitdiff
path: root/ironic/drivers/modules/drac/raid.py
diff options
context:
space:
mode:
Diffstat (limited to 'ironic/drivers/modules/drac/raid.py')
-rw-r--r--ironic/drivers/modules/drac/raid.py165
1 files changed, 163 insertions, 2 deletions
diff --git a/ironic/drivers/modules/drac/raid.py b/ironic/drivers/modules/drac/raid.py
index 4273f06a7..7c83150c1 100644
--- a/ironic/drivers/modules/drac/raid.py
+++ b/ironic/drivers/modules/drac/raid.py
@@ -42,6 +42,11 @@ LOG = logging.getLogger(__name__)
METRICS = metrics_utils.get_metrics_logger(__name__)
+_CURRENT_RAID_CONTROLLER_MODE = "RAIDCurrentControllerMode"
+_REQUESTED_RAID_CONTROLLER_MODE = "RAIDRequestedControllerMode"
+_EHBA_MODE = "Enhanced HBA"
+_RAID_MODE = "RAID"
+
RAID_LEVELS = {
'0': {
'min_disks': 1,
@@ -310,6 +315,71 @@ def clear_foreign_config(node, raid_controller):
raise exception.DracOperationError(error=exc)
+def set_raid_settings(node, controller_fqdd, settings):
+ """Sets the RAID configuration
+
+ It sets the pending_value parameter for each of the attributes
+ passed in. For the values to be applied, a config job must
+ be created.
+
+ :param node: an ironic node object.
+ :param controller_fqdd: the ID of the RAID controller.
+ :param settings: a dictionary containing the proposed values, with
+ each key being the name of attribute and the value
+ being the proposed value.
+ :returns: a dictionary containing:
+ - The is_commit_required key with a boolean value indicating
+ whether a config job must be created for the values to be
+ applied.
+ - The is_reboot_required key with a RebootRequired enumerated
+ value indicating whether the server must be rebooted for the
+ values to be applied. Possible values are true and false.
+ :raises: DRACOperationFailed on error reported back by the DRAC
+ interface
+ """
+ try:
+
+ drac_job.validate_job_queue(node)
+
+ client = drac_common.get_drac_client(node)
+ return client.set_raid_settings(controller_fqdd, settings)
+ except drac_exceptions.BaseClientException as exc:
+ LOG.error('DRAC driver failed to set raid settings '
+ 'on %(raid_controller_fqdd)s '
+ 'for node %(node_uuid)s. '
+ 'Reason: %(error)s.',
+ {'raid_controller_fqdd': controller_fqdd,
+ 'node_uuid': node.uuid,
+ 'error': exc})
+ raise exception.DracOperationError(error=exc)
+
+
+def list_raid_settings(node):
+ """List the RAID configuration settings
+
+ :param node: an ironic node object.
+ :returns: a dictionary with the RAID settings using InstanceID as the
+ key. The attributes are RAIDEnumerableAttribute,
+ RAIDStringAttribute and RAIDIntegerAttribute objects.
+ :raises: DRACOperationFailed on error reported back by the DRAC
+ interface
+ """
+ try:
+
+ drac_job.validate_job_queue(node)
+
+ client = drac_common.get_drac_client(node)
+ return client.list_raid_settings()
+ except drac_exceptions.BaseClientException as exc:
+ LOG.error('DRAC driver failed to list raid settings'
+ 'on %(raid_controller_fqdd)s '
+ 'for node %(node_uuid)s. '
+ 'Reason: %(error)s.',
+ {'node_uuid': node.uuid,
+ 'error': exc})
+ raise exception.DracOperationError(error=exc)
+
+
def change_physical_disk_state(node, mode=None,
controllers_to_physical_disk_ids=None):
"""Convert disks RAID status
@@ -882,6 +952,36 @@ def _validate_volume_size(node, logical_disks):
return logical_disks
+def _switch_to_raid_mode(node, controller_fqdd):
+ """Convert the controller mode from Enhanced HBA to RAID mode
+
+ :param node: an ironic node object
+ :param controller_fqdd: the ID of the RAID controller.
+ :returns: a dictionary containing
+ - The raid_controller key with a ID of the
+ RAID controller value.
+ - The is_commit_required needed key with a
+ boolean value indicating whether a config job must be created
+ for the values to be applied.
+ - The is_reboot_required key with a RebootRequired enumerated
+ value indicating whether the server must be rebooted to
+ switch the controller mode to RAID.
+ """
+ # wait for pending jobs to complete
+ drac_job.wait_for_job_completion(node)
+
+ raid_attr = "{}:{}".format(controller_fqdd,
+ _REQUESTED_RAID_CONTROLLER_MODE)
+ settings = {raid_attr: _RAID_MODE}
+ settings_results = set_raid_settings(
+ node, controller_fqdd, settings)
+ controller = {
+ 'raid_controller': controller_fqdd,
+ 'is_reboot_required': settings_results['is_reboot_required'],
+ 'is_commit_required': settings_results['is_commit_required']}
+ return controller
+
+
def _commit_to_controllers(node, controllers, substep="completed"):
"""Commit changes to RAID controllers on the node.
@@ -926,8 +1026,17 @@ def _commit_to_controllers(node, controllers, substep="completed"):
driver_internal_info['raid_config_job_ids'] = []
optional = drac_constants.RebootRequired.optional
- all_realtime = all(cntlr['is_reboot_required'] == optional
- for cntlr in controllers)
+
+ # all realtime controllers
+ all_realtime = all(
+ (cntlr['is_reboot_required'] == optional)
+ and not(cntlr.get('is_ehba_mode'))
+ for cntlr in controllers)
+
+ # check any controller with ehba mode
+ any_ehba_controllers = any(
+ cntrl.get('is_ehba_mode') is True for cntrl in controllers)
+
raid_config_job_ids = []
raid_config_parameters = []
if all_realtime:
@@ -939,6 +1048,35 @@ def _commit_to_controllers(node, controllers, substep="completed"):
raid_config_job_ids=raid_config_job_ids,
raid_config_parameters=raid_config_parameters)
+ elif any_ehba_controllers:
+ commit_to_ehba_controllers = []
+ for controller in controllers:
+ if controller.get('is_ehba_mode'):
+ job_details = _create_config_job(
+ node, controller=controller['raid_controller'],
+ reboot=False, realtime=True,
+ raid_config_job_ids=raid_config_job_ids,
+ raid_config_parameters=raid_config_parameters)
+
+ ehba_controller = _switch_to_raid_mode(
+ node, controller['raid_controller'])
+ commit_to_ehba_controllers.append(
+ ehba_controller['raid_controller'])
+ else:
+ job_details = _create_config_job(
+ node, controller=controller['raid_controller'],
+ reboot=False, realtime=False,
+ raid_config_job_ids=raid_config_job_ids,
+ raid_config_parameters=raid_config_parameters)
+
+ for controller in commit_to_ehba_controllers:
+ LOG.debug("Create job with Reboot to apply configuration "
+ "changes for ehba controllers")
+ job_details = _create_config_job(
+ node, controller=controller,
+ reboot=(controller == commit_to_ehba_controllers[-1]),
+ realtime=False, raid_config_job_ids=raid_config_job_ids,
+ raid_config_parameters=raid_config_parameters)
else:
for controller in controllers:
mix_controller = controller['raid_controller']
@@ -1004,6 +1142,23 @@ def _create_virtual_disks(task, node):
return _commit_to_controllers(node, controllers)
+def _controller_in_hba_mode(raid_settings, controller_fqdd):
+ controller_mode = raid_settings.get(
+ '{}:{}'.format(controller_fqdd, _CURRENT_RAID_CONTROLLER_MODE))
+
+ return _EHBA_MODE in controller_mode.current_value
+
+
+def _controller_supports_ehba_mode(settings, controller_fqdd):
+ raid_cntrl_attr = "{}:{}".format(controller_fqdd,
+ _CURRENT_RAID_CONTROLLER_MODE)
+ current_cntrl_mode = settings.get(raid_cntrl_attr)
+ if not current_cntrl_mode:
+ return False
+ else:
+ return _EHBA_MODE in current_cntrl_mode.possible_values
+
+
def _get_disk_free_size_mb(disk, pending_delete):
"""Return the size of free space on the disk in MB.
@@ -1371,9 +1526,15 @@ class DracWSManRAID(base.RAIDInterface):
node = task.node
controllers = list()
drac_raid_controllers = list_raid_controllers(node)
+ drac_raid_settings = list_raid_settings(node)
for cntrl in drac_raid_controllers:
if _is_raid_controller(node, cntrl.id, drac_raid_controllers):
controller = dict()
+ if _controller_supports_ehba_mode(
+ drac_raid_settings,
+ cntrl.id) and _controller_in_hba_mode(
+ drac_raid_settings, cntrl.id):
+ controller['is_ehba_mode'] = True
controller_cap = _reset_raid_config(node, cntrl.id)
controller["raid_controller"] = cntrl.id
controller["is_reboot_required"] = controller_cap[