diff options
author | Nisha Agarwal <agarwalnisha1980@gmail.com> | 2017-03-22 00:38:44 -0700 |
---|---|---|
committer | Ilya Etingof <etingof@gmail.com> | 2018-11-03 09:09:56 +0100 |
commit | 41d3356571eafd7f3192d05d7c7523ac295ff5c0 (patch) | |
tree | 54daaeb8536e8d230e35c44c69eea89608b70933 /ironic/drivers/modules/redfish/inspect.py | |
parent | 325b0a6bd42d9eda531ace1185ecdc5e2ceb8614 (diff) | |
download | ironic-41d3356571eafd7f3192d05d7c7523ac295ff5c0.tar.gz |
Add Redfish inspect interface
Add the InspectInterface to the `redfish` hardware type. This enables
OOB inspection in ironic.
Story: 1668487
Task: 10571
Co-Authored-By: Ilya Etingof <etingof@gmail.com>
Depends-On: I3a79f2afe6c838636df554ee468f8f2e0cf0859e
Depends-On: Ieb374f8cabb0418bb2680fdab690446346fc354f
Change-Id: Ie3167569db060620fe0b9784bc7d7a854f2ef754
Diffstat (limited to 'ironic/drivers/modules/redfish/inspect.py')
-rw-r--r-- | ironic/drivers/modules/redfish/inspect.py | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/ironic/drivers/modules/redfish/inspect.py b/ironic/drivers/modules/redfish/inspect.py new file mode 100644 index 000000000..8fc92a15e --- /dev/null +++ b/ironic/drivers/modules/redfish/inspect.py @@ -0,0 +1,192 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +""" +Redfish Inspect Interface +""" + +from oslo_log import log +from oslo_utils import importutils +from oslo_utils import units + +from ironic.common import exception +from ironic.common.i18n import _ +from ironic.common import states +from ironic.drivers import base +from ironic.drivers.modules import deploy_utils +from ironic.drivers.modules.redfish import utils as redfish_utils + +LOG = log.getLogger(__name__) + +sushy = importutils.try_import('sushy') + +if sushy: + CPU_ARCH_MAP = { + sushy.PROCESSOR_ARCH_x86: 'x86_64', + sushy.PROCESSOR_ARCH_IA_64: 'ia64', + sushy.PROCESSOR_ARCH_ARM: 'arm', + sushy.PROCESSOR_ARCH_MIPS: 'mips', + sushy.PROCESSOR_ARCH_OEM: 'oem' + } + + +class RedfishInspect(base.InspectInterface): + + def __init__(self): + """Initialize the Redfish inspection interface. + + :raises: DriverLoadError if the driver can't be loaded due to + missing dependencies + """ + super(RedfishInspect, self).__init__() + if not sushy: + raise exception.DriverLoadError( + driver='redfish', + reason=_('Unable to import the sushy library')) + + def get_properties(self): + """Return the properties of the interface. + + :returns: dictionary of <property name>:<property description> entries. + """ + return redfish_utils.COMMON_PROPERTIES.copy() + + def validate(self, task): + """Validate the driver-specific Node deployment info. + + This method validates whether the 'driver_info' properties of + the task's node contains the required information for this + interface to function. + + This method is often executed synchronously in API requests, so it + should not conduct long-running checks. + + :param task: A TaskManager instance containing the node to act on. + :raises: InvalidParameterValue on malformed parameter(s) + :raises: MissingParameterValue on missing parameter(s) + """ + redfish_utils.parse_driver_info(task.node) + + def inspect_hardware(self, task): + """Inspect hardware to get the hardware properties. + + Inspects hardware to get the essential properties. + It fails if any of the essential properties + are not received from the node. + + :param task: a TaskManager instance. + :raises: HardwareInspectionFailure if essential properties + could not be retrieved successfully. + :returns: The resulting state of inspection. + + """ + system = redfish_utils.get_system(task.node) + + # get the essential properties and update the node properties + # with it. + inspected_properties = task.node.properties + + if system.memory_summary and system.memory_summary.size_gib: + inspected_properties['memory_mb'] = str( + system.memory_summary.size_gib * units.Ki) + + if system.processors and system.processors.summary: + cpus, arch = system.processors.summary + if cpus: + inspected_properties['cpus'] = cpus + + if arch: + try: + inspected_properties['cpu_arch'] = CPU_ARCH_MAP[arch] + + except KeyError: + LOG.warning( + _("Unknown CPU arch %(arch)s discovered " + "for Node %(node)s"), {'node': task.node.uuid, + 'arch': arch}) + + simple_storage_size = 0 + + try: + if (system.simple_storage and + system.simple_storage.disks_sizes_bytes): + simple_storage_size = [ + size for size in system.simple_storage.disks_sizes_bytes + if size >= 4 * units.Gi + ] or [0] + + simple_storage_size = simple_storage_size[0] + + except sushy.SushyError: + LOG.info( + _("No simple storage information discovered " + "for Node %(node)s"), {'node': task.node.uuid}) + + storage_size = 0 + + try: + if system.storage and system.storage.volumes_sizes_bytes: + storage_size = [ + size for size in system.storage.volumes_sizes_bytes + if size >= 4 * units.Gi + ] or [0] + + storage_size = storage_size[0] + + except sushy.SushyError: + LOG.info(_("No storage volume information discovered " + "for Node %(node)s"), {'node': task.node.uuid}) + + local_gb = max(simple_storage_size, storage_size) + + # Note(deray): Convert the received size to GiB and reduce the + # value by 1 GB as consumers like Ironic requires the ``local_gb`` + # to be returned 1 less than actual size. + local_gb = max(0, int(local_gb / units.Gi - 1)) + + if local_gb: + inspected_properties['local_gb'] = str(local_gb) + + else: + LOG.warning(_("Could not provide a valid storage size configured " + "for Node %(node)s"), {'node': task.node.uuid}) + + valid_keys = self.ESSENTIAL_PROPERTIES + missing_keys = valid_keys - set(inspected_properties) + if missing_keys: + error = (_('Failed to discover the following properties: ' + '%(missing_keys)s on node %(node)s'), + {'missing_keys': ', '.join(missing_keys), + 'node': task.node.uuid}) + raise exception.HardwareInspectionFailure(error=error) + + task.node.properties = inspected_properties + task.node.save() + + LOG.debug(_("Node properties for %(node)s are updated as " + "%(properties)s"), + {'properties': inspected_properties, + 'node': task.node.uuid}) + + if (system.ethernet_interfaces and + system.ethernet_interfaces.eth_summary): + macs = system.ethernet_interfaces.eth_summary + + # Create ports for the nics detected. + deploy_utils.create_ports_if_not_exist(task, macs) + + else: + LOG.info(_("No NIC information discovered " + "for Node %(node)s"), {'node': task.node.uuid}) + + LOG.info(_("Node %(node)s inspected."), {'node': task.node.uuid}) + + return states.MANAGEABLE |