Add first idrac HW type Redfish interface support

This change adds initial idrac hardware type support of interface
implementations that utilize the Redfish out-of-band (OOB) management
protocol and are compatible with the integrated Dell Remote Access
Controller (iDRAC) baseboard management controller (BMC), presently
those of the management and power hardware interfaces. They are named
'idrac-redfish'.

It also introduces a new name for the 'idrac' interface implementations,
'idrac-wsman', and deprecates 'idrac'. They both use the Web Services
Management (WS-Man) OOB management protocol.

The idrac hardware type declares support for those new interface
implementations, in addition to all interface implementations it has
been supporting. The priority order of supported interfaces remains the
same. Interface implementations which rely on WS-Man continue to have
the highest priority, and the new 'idrac-wsman' is listed before the
deprecated 'idrac'.

Story: 2004592
Task: 36275
Change-Id: I11f002eff78d27369b3dbe9a9fbd5fc73496a5eb
This commit is contained in:
Richard Pioso 2019-08-12 18:08:04 -04:00
parent aba282a7fc
commit 03471be1ed
10 changed files with 226 additions and 27 deletions

View File

@ -38,12 +38,13 @@ class IDRACHardware(generic.GenericHardware):
@property
def supported_management_interfaces(self):
"""List of supported management interfaces."""
return [management.DracManagement]
return [management.DracWSManManagement, management.DracManagement,
management.DracRedfishManagement]
@property
def supported_power_interfaces(self):
"""List of supported power interfaces."""
return [power.DracPower]
return [power.DracWSManPower, power.DracPower, power.DracRedfishPower]
# Optional hardware interfaces
@ -53,14 +54,16 @@ class IDRACHardware(generic.GenericHardware):
# Inspector support should have a higher priority than NoInspect
# if it is enabled by an operator (implying that the service is
# installed).
return [drac_inspect.DracInspect, inspector.Inspector, noop.NoInspect]
return [drac_inspect.DracWSManInspect, drac_inspect.DracInspect,
inspector.Inspector, noop.NoInspect]
@property
def supported_raid_interfaces(self):
"""List of supported raid interfaces."""
return [raid.DracRAID, noop.NoRAID]
return [raid.DracWSManRAID, raid.DracRAID, noop.NoRAID]
@property
def supported_vendor_interfaces(self):
"""List of supported vendor interfaces."""
return [vendor_passthru.DracVendorPassthru, noop.NoVendor]
return [vendor_passthru.DracWSManVendorPassthru,
vendor_passthru.DracVendorPassthru, noop.NoVendor]

View File

@ -35,7 +35,7 @@ LOG = logging.getLogger(__name__)
METRICS = metrics_utils.get_metrics_logger(__name__)
class DracInspect(base.InspectInterface):
class DracWSManInspect(base.InspectInterface):
def get_properties(self):
"""Return the properties of the interface.
@ -221,3 +221,20 @@ class DracInspect(base.InspectInterface):
pxe_dev_nics.append(nic.id)
return pxe_dev_nics
class DracInspect(DracWSManInspect):
"""Class alias of class DracWSManInspect.
This class provides ongoing support of the deprecated 'idrac'
inspect interface implementation entrypoint.
All bug fixes and new features should be implemented in its base
class, DracWSManInspect. That makes them available to both the
deprecated 'idrac' and new 'idrac-wsman' entrypoints. Such changes
should not be made to this class.
"""
def __init__(self):
LOG.warning("Inspect interface 'idrac' is deprecated and may be "
"removed in a future release. Use 'idrac-wsman' instead.")

View File

@ -2,7 +2,7 @@
#
# Copyright 2014 Red Hat, Inc.
# All Rights Reserved.
# Copyright (c) 2017-2018 Dell Inc. or its subsidiaries.
# Copyright (c) 2017-2019 Dell Inc. or its subsidiaries.
#
# 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
@ -34,6 +34,7 @@ from ironic.conf import CONF
from ironic.drivers import base
from ironic.drivers.modules.drac import common as drac_common
from ironic.drivers.modules.drac import job as drac_job
from ironic.drivers.modules.redfish import management as redfish_management
drac_exceptions = importutils.try_import('dracclient.exceptions')
@ -294,7 +295,18 @@ def set_boot_device(node, device, persistent=False):
raise exception.DracOperationError(error=exc)
class DracManagement(base.ManagementInterface):
class DracRedfishManagement(redfish_management.RedfishManagement):
"""iDRAC Redfish interface for management-related actions.
Presently, this class entirely defers to its base class, a generic,
vendor-independent Redfish interface. Future resolution of Dell EMC-
specific incompatibilities and introduction of vendor value added
should be implemented by this class.
"""
pass
class DracWSManManagement(base.ManagementInterface):
def get_properties(self):
"""Return the properties of the interface."""
@ -446,3 +458,20 @@ class DracManagement(base.ManagementInterface):
'%(node_uuid)s. Reason: %(error)s.',
{'node_uuid': node.uuid, 'error': exc})
raise exception.DracOperationError(error=exc)
class DracManagement(DracWSManManagement):
"""Class alias of class DracWSManManagement.
This class provides ongoing support of the deprecated 'idrac'
management interface implementation entrypoint.
All bug fixes and new features should be implemented in its base
class, DracWSManManagement. That makes them available to both the
deprecated 'idrac' and new 'idrac-wsman' entrypoints. Such changes
should not be made to this class.
"""
def __init__(self):
LOG.warning("Management interface 'idrac' is deprecated and may be "
"removed in a future release. Use 'idrac-wsman' instead.")

View File

@ -25,6 +25,7 @@ from ironic.conductor import task_manager
from ironic.drivers import base
from ironic.drivers.modules.drac import common as drac_common
from ironic.drivers.modules.drac import management as drac_management
from ironic.drivers.modules.redfish import power as redfish_power
drac_constants = importutils.try_import('dracclient.constants')
drac_exceptions = importutils.try_import('dracclient.exceptions')
@ -114,7 +115,18 @@ def _set_power_state(node, power_state):
raise exception.DracOperationError(error=exc)
class DracPower(base.PowerInterface):
class DracRedfishPower(redfish_power.RedfishPower):
"""iDRAC Redfish interface for power-related actions.
Presently, this class entirely defers to its base class, a generic,
vendor-independent Redfish interface. Future resolution of Dell EMC-
specific incompatibilities and introduction of vendor value added
should be implemented by this class.
"""
pass
class DracWSManPower(base.PowerInterface):
"""Interface for power-related actions."""
def get_properties(self):
@ -194,3 +206,20 @@ class DracPower(base.PowerInterface):
target_power_state = states.POWER_ON
_set_power_state(task.node, target_power_state)
class DracPower(DracWSManPower):
"""Class alias of class DracWSManPower.
This class provides ongoing support of the deprecated 'idrac' power
interface implementation entrypoint.
All bug fixes and new features should be implemented in its base
class, DracWSManPower. That makes them available to both the
deprecated 'idrac' and new 'idrac-wsman' entrypoints. Such changes
should not be made to this class.
"""
def __init__(self):
LOG.warning("Power interface 'idrac' is deprecated and may be removed "
"in a future release. Use 'idrac-wsman' instead.")

View File

@ -801,7 +801,7 @@ def _commit_to_controllers(node, controllers, substep="completed"):
return states.CLEANWAIT
class DracRAID(base.RAIDInterface):
class DracWSManRAID(base.RAIDInterface):
def get_properties(self):
"""Return the properties of the interface."""
@ -1093,3 +1093,20 @@ class DracRAID(base.RAIDInterface):
task.node.driver_internal_info = driver_internal_info
task.node.save()
manager_utils.notify_conductor_resume_clean(task)
class DracRAID(DracWSManRAID):
"""Class alias of class DracWSManRAID.
This class provides ongoing support of the deprecated 'idrac' RAID
interface implementation entrypoint.
All bug fixes and new features should be implemented in its base
class, DracWSManRAID. That makes them available to both the
deprecated 'idrac' and new 'idrac-wsman' entrypoints. Such changes
should not be made to this class.
"""
def __init__(self):
LOG.warning("RAID interface 'idrac' is deprecated and may be removed "
"in a future release. Use 'idrac-wsman' instead.")

View File

@ -16,6 +16,7 @@ DRAC vendor-passthru interface
"""
from ironic_lib import metrics_utils
from oslo_log import log as logging
from ironic.common.i18n import _
from ironic.conductor import task_manager
@ -24,10 +25,12 @@ from ironic.drivers.modules.drac import bios as drac_bios
from ironic.drivers.modules.drac import common as drac_common
from ironic.drivers.modules.drac import job as drac_job
LOG = logging.getLogger(__name__)
METRICS = metrics_utils.get_metrics_logger(__name__)
class DracVendorPassthru(base.VendorInterface):
class DracWSManVendorPassthru(base.VendorInterface):
"""Interface for DRAC specific methods."""
def get_properties(self):
@ -168,3 +171,21 @@ class DracVendorPassthru(base.VendorInterface):
jobs = drac_job.list_unfinished_jobs(task.node)
# FIXME(mgould) Do this without calling private methods.
return {'unfinished_jobs': [job._asdict() for job in jobs]}
class DracVendorPassthru(DracWSManVendorPassthru):
"""Class alias of class DracWSManVendorPassthru.
This class provides ongoing support of the deprecated 'idrac' vendor
passthru interface implementation entrypoint.
All bug fixes and new features should be implemented in its base
class, DracWSManVendorPassthru. That makes them available to both
the deprecated 'idrac' and new 'idrac-wsman' entrypoints. Such
changes should not be made to this class.
"""
def __init__(self):
LOG.warning("Vendor passthru interface 'idrac' is deprecated and may "
"be removed in a future release. Use 'idrac-wsman' "
"instead.")

View File

@ -29,11 +29,13 @@ class BaseDracTest(db_base.DbTestCase):
def setUp(self):
super(BaseDracTest, self).setUp()
self.config(enabled_hardware_types=['idrac', 'fake-hardware'],
enabled_power_interfaces=['idrac', 'fake'],
enabled_management_interfaces=['idrac', 'fake'],
enabled_inspect_interfaces=['idrac', 'fake', 'no-inspect'],
enabled_vendor_interfaces=['idrac', 'fake', 'no-vendor'],
enabled_raid_interfaces=['idrac', 'fake', 'no-raid'])
enabled_power_interfaces=['idrac-wsman', 'fake'],
enabled_management_interfaces=['idrac-wsman', 'fake'],
enabled_inspect_interfaces=[
'idrac-wsman', 'fake', 'no-inspect'],
enabled_vendor_interfaces=[
'idrac-wsman', 'fake', 'no-vendor'],
enabled_raid_interfaces=['idrac-wsman', 'fake', 'no-raid'])
class DictToObj(object):

View File

@ -1,4 +1,4 @@
# Copyright (c) 2017 Dell Inc. or its subsidiaries.
# Copyright (c) 2017-2019 Dell Inc. or its subsidiaries.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -30,13 +30,17 @@ class IDRACHardwareTestCase(db_base.DbTestCase):
def setUp(self):
super(IDRACHardwareTestCase, self).setUp()
self.config(enabled_hardware_types=['idrac'],
enabled_management_interfaces=['idrac'],
enabled_power_interfaces=['idrac'],
enabled_management_interfaces=[
'idrac', 'idrac-wsman', 'idrac-redfish'],
enabled_power_interfaces=[
'idrac', 'idrac-wsman', 'idrac-redfish'],
enabled_inspect_interfaces=[
'idrac', 'inspector', 'no-inspect'],
'idrac', 'idrac-wsman', 'inspector', 'no-inspect'],
enabled_network_interfaces=['flat', 'neutron', 'noop'],
enabled_raid_interfaces=['idrac', 'no-raid'],
enabled_vendor_interfaces=['idrac', 'no-vendor'])
enabled_raid_interfaces=[
'idrac', 'idrac-wsman', 'no-raid'],
enabled_vendor_interfaces=[
'idrac', 'idrac-wsman', 'no-vendor'])
def _validate_interfaces(self, driver, **kwargs):
self.assertIsInstance(
@ -47,10 +51,10 @@ class IDRACHardwareTestCase(db_base.DbTestCase):
kwargs.get('deploy', iscsi_deploy.ISCSIDeploy))
self.assertIsInstance(
driver.management,
kwargs.get('management', drac.management.DracManagement))
kwargs.get('management', drac.management.DracWSManManagement))
self.assertIsInstance(
driver.power,
kwargs.get('power', drac.power.DracPower))
kwargs.get('power', drac.power.DracWSManPower))
self.assertIsInstance(
driver.console,
@ -58,7 +62,7 @@ class IDRACHardwareTestCase(db_base.DbTestCase):
self.assertIsInstance(
driver.inspect,
kwargs.get('inspect', drac.inspect.DracInspect))
kwargs.get('inspect', drac.inspect.DracWSManInspect))
self.assertIsInstance(
driver.network,
@ -66,7 +70,7 @@ class IDRACHardwareTestCase(db_base.DbTestCase):
self.assertIsInstance(
driver.raid,
kwargs.get('raid', drac.raid.DracRAID))
kwargs.get('raid', drac.raid.DracWSManRAID))
self.assertIsInstance(
driver.storage,
@ -74,7 +78,7 @@ class IDRACHardwareTestCase(db_base.DbTestCase):
self.assertIsInstance(
driver.vendor,
kwargs.get('vendor', drac.vendor_passthru.DracVendorPassthru))
kwargs.get('vendor', drac.vendor_passthru.DracWSManVendorPassthru))
def test_default_interfaces(self):
node = obj_utils.create_test_node(self.context, driver='idrac')
@ -110,3 +114,29 @@ class IDRACHardwareTestCase(db_base.DbTestCase):
with task_manager.acquire(self.context, node.id) as task:
self._validate_interfaces(task.driver,
vendor=noop.NoVendor)
def test_override_with_idrac(self):
node = obj_utils.create_test_node(self.context, driver='idrac',
management_interface='idrac',
power_interface='idrac',
inspect_interface='idrac',
raid_interface='idrac',
vendor_interface='idrac')
with task_manager.acquire(self.context, node.id) as task:
self._validate_interfaces(
task.driver,
management=drac.management.DracManagement,
power=drac.power.DracPower,
inspect=drac.inspect.DracInspect,
raid=drac.raid.DracRAID,
vendor=drac.vendor_passthru.DracVendorPassthru)
def test_override_with_redfish_management_and_power(self):
node = obj_utils.create_test_node(self.context, driver='idrac',
management_interface='idrac-redfish',
power_interface='idrac-redfish')
with task_manager.acquire(self.context, node.id) as task:
self._validate_interfaces(
task.driver,
management=drac.management.DracRedfishManagement,
power=drac.power.DracRedfishPower)

View File

@ -0,0 +1,44 @@
---
features:
- |
Adds initial ``idrac`` hardware type support of interface
implementations that utilize the Redfish out-of-band (OOB)
management protocol and are compatible with the integrated Dell
Remote Access Controller (iDRAC) baseboard management controller
(BMC), presently those of the management and power hardware
interfaces. They are named ``idrac-redfish``.
Introduces a new name for the ``idrac`` interface implementations,
``idrac-wsman``, and deprecates ``idrac``. They both use the Web
Services Management (WS-Man) OOB management protocol.
The ``idrac`` hardware type declares support for those new interface
implementations, in addition to all interface implementations it has
been supporting. The priority order of supported interfaces remains
the same. Interface implementations which rely on WS-Man continue to
have the highest priority, and the new ``idrac-wsman`` is listed
before the deprecated ``idrac``. It now supports the following
interface implementations, which are listed in priority order from
highest to lowest:
* bios: ``no-bios``
* boot: ``ipxe``, ``pxe``
* console: ``no-console``
* deploy: ``iscsi``, ``direct``, ``ansible``, ``ramdisk``
* inspect: ``idrac-wsman``, ``idrac``, ``inspector``, ``no-inspect``
* management: ``idrac-wsman``, ``idrac``, ``idrac-redfish``
* network: ``flat``, ``neutron``, ``noop``
* power: ``idrac-wsman``, ``idrac``, ``idrac-redfish``
* raid: ``idrac-wsman``, ``idrac``, ``no-raid``
* rescue: ``no-rescue``, ``agent``
* storage: ``noop``, ``cinder``, ``external``
* vendor: ``idrac-wsman``, ``idrac``, ``no-vendor``
For more information, see `story 2004592
<https://storyboard.openstack.org/#!/story/2004592>`_.
deprecations:
- |
The ``idrac`` interface implementation name is deprecated in favor
of a new name, ``idrac-wsman``, and may be removed in a future
release. A deprecation warning will be logged for every loaded
``idrac`` interface implementation. Use ``idrac-wsman`` instead.

View File

@ -89,6 +89,7 @@ ironic.hardware.interfaces.deploy =
ironic.hardware.interfaces.inspect =
fake = ironic.drivers.modules.fake:FakeInspect
idrac = ironic.drivers.modules.drac.inspect:DracInspect
idrac-wsman = ironic.drivers.modules.drac.inspect:DracWSManInspect
ilo = ironic.drivers.modules.ilo.inspect:IloInspect
inspector = ironic.drivers.modules.inspector:Inspector
irmc = ironic.drivers.modules.irmc.inspect:IRMCInspect
@ -99,6 +100,8 @@ ironic.hardware.interfaces.management =
fake = ironic.drivers.modules.fake:FakeManagement
ibmc = ironic.drivers.modules.ibmc.management:IBMCManagement
idrac = ironic.drivers.modules.drac.management:DracManagement
idrac-redfish = ironic.drivers.modules.drac.management:DracRedfishManagement
idrac-wsman = ironic.drivers.modules.drac.management:DracWSManManagement
ilo = ironic.drivers.modules.ilo.management:IloManagement
ilo5 = ironic.drivers.modules.ilo.management:Ilo5Management
intel-ipmitool = ironic.drivers.modules.intel_ipmi.management:IntelIPMIManagement
@ -117,6 +120,8 @@ ironic.hardware.interfaces.power =
fake = ironic.drivers.modules.fake:FakePower
ibmc = ironic.drivers.modules.ibmc.power:IBMCPower
idrac = ironic.drivers.modules.drac.power:DracPower
idrac-redfish = ironic.drivers.modules.drac.power:DracRedfishPower
idrac-wsman = ironic.drivers.modules.drac.power:DracWSManPower
ilo = ironic.drivers.modules.ilo.power:IloPower
ipmitool = ironic.drivers.modules.ipmitool:IPMIPower
irmc = ironic.drivers.modules.irmc.power:IRMCPower
@ -128,6 +133,7 @@ ironic.hardware.interfaces.raid =
agent = ironic.drivers.modules.agent:AgentRAID
fake = ironic.drivers.modules.fake:FakeRAID
idrac = ironic.drivers.modules.drac.raid:DracRAID
idrac-wsman = ironic.drivers.modules.drac.raid:DracWSManRAID
ilo5 = ironic.drivers.modules.ilo.raid:Ilo5RAID
irmc = ironic.drivers.modules.irmc.raid:IRMCRAID
no-raid = ironic.drivers.modules.noop:NoRAID
@ -147,6 +153,7 @@ ironic.hardware.interfaces.vendor =
fake = ironic.drivers.modules.fake:FakeVendorB
ibmc = ironic.drivers.modules.ibmc.vendor:IBMCVendor
idrac = ironic.drivers.modules.drac.vendor_passthru:DracVendorPassthru
idrac-wsman = ironic.drivers.modules.drac.vendor_passthru:DracWSManVendorPassthru
ilo = ironic.drivers.modules.ilo.vendor:VendorPassthru
ipmitool = ironic.drivers.modules.ipmitool:VendorPassthru
no-vendor = ironic.drivers.modules.noop:NoVendor