summaryrefslogtreecommitdiff
path: root/ironic/drivers/modules/redfish/management.py
diff options
context:
space:
mode:
authorIlya Etingof <etingof@gmail.com>2019-04-15 15:49:59 +0200
committerIlya Etingof <etingof@gmail.com>2019-11-21 12:35:24 +0100
commite8f2120405a4ee5702c239fc65908097d4c6216a (patch)
tree5301bfb5d10058cf958208c2a40bf76b127696c3 /ironic/drivers/modules/redfish/management.py
parent8990e7dcbc5ab24344bd5778c417525147fd0cfd (diff)
downloadironic-e8f2120405a4ee5702c239fc65908097d4c6216a.tar.gz
Add indicator management to redfish hw type
Implements necessary indicator management calls to redfish driver to actually read/set system/chassis and drive LEDs through Redfish. The spec: https://review.opendev.org/#/c/655685/7/specs/approved/expose-hardware-indicators.rst Change-Id: Ib9ccdfa41974cd353af8a517dc2917f129e49e03 Story: 2005342 Task: 30471
Diffstat (limited to 'ironic/drivers/modules/redfish/management.py')
-rw-r--r--ironic/drivers/modules/redfish/management.py209
1 files changed, 209 insertions, 0 deletions
diff --git a/ironic/drivers/modules/redfish/management.py b/ironic/drivers/modules/redfish/management.py
index f17f6c654..591f46ae0 100644
--- a/ironic/drivers/modules/redfish/management.py
+++ b/ironic/drivers/modules/redfish/management.py
@@ -20,8 +20,10 @@ from oslo_utils import importutils
from ironic.common import boot_devices
from ironic.common import boot_modes
+from ironic.common import components
from ironic.common import exception
from ironic.common.i18n import _
+from ironic.common import indicator_states
from ironic.conductor import task_manager
from ironic.drivers import base
from ironic.drivers.modules.redfish import utils as redfish_utils
@@ -55,6 +57,16 @@ if sushy:
BOOT_DEVICE_PERSISTENT_MAP_REV = {v: k for k, v in
BOOT_DEVICE_PERSISTENT_MAP.items()}
+ INDICATOR_MAP = {
+ sushy.INDICATOR_LED_LIT: indicator_states.ON,
+ sushy.INDICATOR_LED_OFF: indicator_states.OFF,
+ sushy.INDICATOR_LED_BLINKING: indicator_states.BLINKING,
+ sushy.INDICATOR_LED_UNKNOWN: indicator_states.UNKNOWN
+ }
+
+ INDICATOR_MAP_REV = {
+ v: k for k, v in INDICATOR_MAP.items()}
+
class RedfishManagement(base.ManagementInterface):
@@ -393,3 +405,200 @@ class RedfishManagement(base.ManagementInterface):
'error': e})
LOG.error(error_msg)
raise exception.RedfishError(error=error_msg)
+
+ def get_supported_indicators(self, task, component=None):
+ """Get a map of the supported indicators (e.g. LEDs).
+
+ :param task: A task from TaskManager.
+ :param component: If not `None`, return indicator information
+ for just this component, otherwise return indicators for
+ all existing components.
+ :returns: A dictionary of hardware components
+ (:mod:`ironic.common.components`) as keys with values
+ being dictionaries having indicator IDs as keys and indicator
+ properties as values.
+
+ ::
+
+ {
+ 'chassis': {
+ 'enclosure-0': {
+ "readonly": true,
+ "states": [
+ "OFF",
+ "ON"
+ ]
+ }
+ },
+ 'system':
+ 'blade-A': {
+ "readonly": true,
+ "states": [
+ "OFF",
+ "ON"
+ ]
+ }
+ },
+ 'drive':
+ 'ssd0': {
+ "readonly": true,
+ "states": [
+ "OFF",
+ "ON"
+ ]
+ }
+ }
+ }
+ """
+ properties = {
+ "readonly": False,
+ "states": [
+ indicator_states.BLINKING,
+ indicator_states.OFF,
+ indicator_states.ON
+ ]
+ }
+
+ indicators = {}
+
+ system = redfish_utils.get_system(task.node)
+
+ try:
+ if component in (None, components.CHASSIS) and system.chassis:
+ indicators[components.CHASSIS] = {
+ chassis.uuid: properties for chassis in system.chassis
+ if chassis.indicator_led
+ }
+
+ except sushy.exceptions.SushyError as e:
+ LOG.debug('Chassis indicator not available for node %(node)s: '
+ '%(error)s', {'node': task.node.uuid, 'error': e})
+
+ try:
+ if component in (None, components.SYSTEM) and system.indicator_led:
+ indicators[components.SYSTEM] = {
+ system.uuid: properties
+ }
+
+ except sushy.exceptions.SushyError as e:
+ LOG.debug('System indicator not available for node %(node)s: '
+ '%(error)s', {'node': task.node.uuid, 'error': e})
+
+ try:
+ if (component in (None, components.DISK) and
+ system.simple_storage and system.simple_storage.drives):
+ indicators[components.DISK] = {
+ drive.uuid: properties
+ for drive in system.simple_storage.drives
+ if drive.indicator_led
+ }
+
+ except sushy.exceptions.SushyError as e:
+ LOG.debug('Drive indicator not available for node %(node)s: '
+ '%(error)s', {'node': task.node.uuid, 'error': e})
+
+ return indicators
+
+ def set_indicator_state(self, task, component, indicator, state):
+ """Set indicator on the hardware component to the desired state.
+
+ :param task: A task from TaskManager.
+ :param component: The hardware component, one of
+ :mod:`ironic.common.components`.
+ :param indicator: Indicator ID (as reported by
+ `get_supported_indicators`).
+ :param state: Desired state of the indicator, one of
+ :mod:`ironic.common.indicator_states`.
+ :raises: InvalidParameterValue if an invalid component, indicator
+ or state is specified.
+ :raises: MissingParameterValue if a required parameter is missing
+ :raises: RedfishError on an error from the Sushy library
+ """
+ system = redfish_utils.get_system(task.node)
+
+ try:
+ if (component == components.SYSTEM
+ and indicator == system.uuid):
+ system.set_indicator_led(INDICATOR_MAP_REV[state])
+ return
+
+ elif (component == components.CHASSIS
+ and system.chassis):
+ for chassis in system.chassis:
+ if chassis.uuid == indicator:
+ chassis.set_indicator_led(
+ INDICATOR_MAP_REV[state])
+ return
+
+ elif (component == components.DISK and
+ system.simple_storage and system.simple_storage.drives):
+ for drive in system.simple_storage.drives:
+ if drive.uuid == indicator:
+ drive.set_indicator_led(
+ INDICATOR_MAP_REV[state])
+ return
+
+ except sushy.exceptions.SushyError as e:
+ error_msg = (_('Redfish set %(component)s indicator %(indicator)s '
+ 'state %(state)s failed for node %(node)s. Error: '
+ '%(error)s') % {'component': component,
+ 'indicator': indicator,
+ 'state': state,
+ 'node': task.node.uuid,
+ 'error': e})
+ LOG.error(error_msg)
+ raise exception.RedfishError(error=error_msg)
+
+ raise exception.MissingParameterValue(_(
+ "Unknown indicator %(indicator)s for component %(component)s of "
+ "node %(uuid)s") % {'indicator': indicator,
+ 'component': component,
+ 'uuid': task.node.uuid})
+
+ def get_indicator_state(self, task, component, indicator):
+ """Get current state of the indicator of the hardware component.
+
+ :param task: A task from TaskManager.
+ :param component: The hardware component, one of
+ :mod:`ironic.common.components`.
+ :param indicator: Indicator ID (as reported by
+ `get_supported_indicators`).
+ :raises: MissingParameterValue if a required parameter is missing
+ :raises: RedfishError on an error from the Sushy library
+ :returns: Current state of the indicator, one of
+ :mod:`ironic.common.indicator_states`.
+ """
+ system = redfish_utils.get_system(task.node)
+
+ try:
+ if (component == components.SYSTEM
+ and indicator == system.uuid):
+ return INDICATOR_MAP[system.indicator_led]
+
+ if (component == components.CHASSIS
+ and system.chassis):
+ for chassis in system.chassis:
+ if chassis.uuid == indicator:
+ return INDICATOR_MAP[chassis.indicator_led]
+
+ if (component == components.DISK and
+ system.simple_storage and system.simple_storage.drives):
+ for drive in system.simple_storage.drives:
+ if drive.uuid == indicator:
+ return INDICATOR_MAP[drive.indicator_led]
+
+ except sushy.exceptions.SushyError as e:
+ error_msg = (_('Redfish get %(component)s indicator %(indicator)s '
+ 'state failed for node %(node)s. Error: '
+ '%(error)s') % {'component': component,
+ 'indicator': indicator,
+ 'node': task.node.uuid,
+ 'error': e})
+ LOG.error(error_msg)
+ raise exception.RedfishError(error=error_msg)
+
+ raise exception.MissingParameterValue(_(
+ "Unknown indicator %(indicator)s for component %(component)s of "
+ "node %(uuid)s") % {'indicator': indicator,
+ 'component': component,
+ 'uuid': task.node.uuid})