From f14794ca2e6115a0b025f673dce5bee0ac2aec90 Mon Sep 17 00:00:00 2001
From: Julia Kreger <juliaashleykreger@gmail.com>
Date: Tue, 18 Jun 2024 16:08:58 -0700
Subject: [PATCH] Remove ibmc hardware type

There has been no testing of this hardware type in quite some time,
and the last we heard the vendor was moving towards redfish.

Change-Id: Ib32db463981ec54430884ac760956b7c7b40b17f
---
 devstack/lib/ironic                           |  24 --
 doc/source/admin/drivers.rst                  |   1 -
 doc/source/admin/drivers/ibmc.rst             | 323 ------------------
 driver-requirements.txt                       |   3 -
 ironic/common/exception.py                    |   8 -
 ironic/conf/__init__.py                       |   2 -
 ironic/conf/ibmc.py                           |  35 --
 ironic/drivers/ibmc.py                        |  47 ---
 ironic/drivers/modules/ibmc/management.py     | 241 -------------
 ironic/drivers/modules/ibmc/mappings.py       |  70 ----
 ironic/drivers/modules/ibmc/power.py          | 149 --------
 ironic/drivers/modules/ibmc/raid.py           | 203 -----------
 ironic/drivers/modules/ibmc/utils.py          | 172 ----------
 ironic/drivers/modules/ibmc/vendor.py         | 112 ------
 ironic/tests/unit/db/utils.py                 |   9 -
 .../tests/unit/drivers/modules/ibmc/base.py   |  43 ---
 .../drivers/modules/ibmc/test_management.py   | 294 ----------------
 .../unit/drivers/modules/ibmc/test_power.py   | 288 ----------------
 .../unit/drivers/modules/ibmc/test_raid.py    | 167 ---------
 .../unit/drivers/modules/ibmc/test_utils.py   | 173 ----------
 .../unit/drivers/modules/ibmc/test_vendor.py  |  79 -----
 .../unit/drivers/modules/intel_ipmi/base.py   |   2 +-
 ironic/tests/unit/drivers/test_ibmc.py        |  52 ---
 .../drivers/third_party_driver_mock_specs.py  |   7 -
 .../unit/drivers/third_party_driver_mocks.py  |  42 ---
 ...precated-ibmc-driver-0c90817d8ad0ccc4.yaml |   4 +
 setup.cfg                                     |   5 -
 27 files changed, 5 insertions(+), 2550 deletions(-)
 delete mode 100644 doc/source/admin/drivers/ibmc.rst
 delete mode 100644 ironic/conf/ibmc.py
 delete mode 100644 ironic/drivers/ibmc.py
 delete mode 100644 ironic/drivers/modules/ibmc/management.py
 delete mode 100644 ironic/drivers/modules/ibmc/mappings.py
 delete mode 100644 ironic/drivers/modules/ibmc/power.py
 delete mode 100644 ironic/drivers/modules/ibmc/raid.py
 delete mode 100644 ironic/drivers/modules/ibmc/utils.py
 delete mode 100644 ironic/drivers/modules/ibmc/vendor.py
 delete mode 100644 ironic/tests/unit/drivers/modules/ibmc/base.py
 delete mode 100644 ironic/tests/unit/drivers/modules/ibmc/test_management.py
 delete mode 100644 ironic/tests/unit/drivers/modules/ibmc/test_power.py
 delete mode 100644 ironic/tests/unit/drivers/modules/ibmc/test_raid.py
 delete mode 100644 ironic/tests/unit/drivers/modules/ibmc/test_utils.py
 delete mode 100644 ironic/tests/unit/drivers/modules/ibmc/test_vendor.py
 delete mode 100644 ironic/tests/unit/drivers/test_ibmc.py
 create mode 100644 releasenotes/notes/remove-deprecated-ibmc-driver-0c90817d8ad0ccc4.yaml

diff --git a/devstack/lib/ironic b/devstack/lib/ironic
index cb1ef003e5..65ea02621d 100644
--- a/devstack/lib/ironic
+++ b/devstack/lib/ironic
@@ -842,26 +842,11 @@ function is_deployed_by_irmc {
     return 1
 }
 
-function is_deployed_by_ibmc {
-    [[ "$IRONIC_DEPLOY_DRIVER" == ibmc ]] && return 0
-    return 1
-}
-
 function is_drac_enabled {
     [[ -z "${IRONIC_ENABLED_HARDWARE_TYPES%%*idrac*}" ]] && return 0
     return 1
 }
 
-function is_ibmc_enabled {
-    [[ -z "${IRONIC_ENABLED_HARDWARE_TYPES%%*ibmc*}" ]] && return 0
-    return 1
-}
-
-function is_irmc_enabled {
-    [[ -z "${IRONIC_ENABLED_HARDWARE_TYPES%%*irmc*}" ]] && return 0
-    return 1
-}
-
 function is_ansible_deploy_enabled {
     [[ -z "${IRONIC_ENABLED_DEPLOY_INTERFACES%%*ansible*}" ]] && return 0
     return 1
@@ -1183,10 +1168,6 @@ function install_ironic {
         pip_install python-dracclient
     fi
 
-    if is_ibmc_enabled; then
-        pip_install python-ibmcclient
-    fi
-
     if is_irmc_enabled; then
         pip_install python-scciclient pysnmp
     fi
@@ -2598,11 +2579,6 @@ function enroll_nodes {
                 if [[ -n "$IRONIC_DEPLOY_ISO_ID" ]]; then
                     node_options+=" --driver-info deploy_iso=$IRONIC_DEPLOY_ISO_ID"
                 fi
-            elif is_deployed_by_ibmc; then
-                node_options+=" --driver-info ibmc_address=$bmc_address \
-                    --driver-info ibmc_username=$bmc_username \
-                    --driver-info ibmc_password=$bmc_passwd \
-                    --driver-info ibmc_verify_ca=False"
             fi
 
             interface_info="${mac_address}"
diff --git a/doc/source/admin/drivers.rst b/doc/source/admin/drivers.rst
index 988f1376a1..e2bae7d9da 100644
--- a/doc/source/admin/drivers.rst
+++ b/doc/source/admin/drivers.rst
@@ -17,7 +17,6 @@ Hardware Types
 .. toctree::
   :maxdepth: 1
 
-  drivers/ibmc
   drivers/idrac
   drivers/ilo
   drivers/intel-ipmi
diff --git a/doc/source/admin/drivers/ibmc.rst b/doc/source/admin/drivers/ibmc.rst
deleted file mode 100644
index 8a173a8ad8..0000000000
--- a/doc/source/admin/drivers/ibmc.rst
+++ /dev/null
@@ -1,323 +0,0 @@
-===============
-iBMC driver
-===============
-
-Overview
-========
-
-.. warning::
-   The ``ibmc`` driver has been deprecated and is anticipated to be removed
-   from Ironic at some point during or after the 2024.2 development cycle.
-   The anticipated forward management path is to migrate to the ``redfish``
-   hardware type.
-
-The ``ibmc`` driver is targeted for Huawei V5 series rack server such as
-2288H V5, CH121 V5. The iBMC hardware type enables the user to take advantage
-of features of `Huawei iBMC`_ to control Huawei server.
-
-The ``ibmc`` hardware type supports the following Ironic interfaces:
-
-* Management Interface: Boot device management
-* Power Interface: Power management
-* `RAID Interface`_: RAID controller and disk management
-* `Vendor Interface`_: ibmc passthru interfaces
-
-Prerequisites
-=============
-
-The `HUAWEI iBMC Client library`_ should be installed on the ironic conductor
-  node(s).
-
-For example, it can be installed with ``pip``::
-
-    sudo pip install python-ibmcclient
-
-Enabling the iBMC driver
-============================
-
-#. Add ``ibmc`` to the list of ``enabled_hardware_types``,
-   ``enabled_power_interfaces``, ``enabled_vendor_interfaces``
-   and ``enabled_management_interfaces`` in ``/etc/ironic/ironic.conf``. For example::
-
-    [DEFAULT]
-    ...
-    enabled_hardware_types = ibmc
-    enabled_power_interfaces = ibmc
-    enabled_management_interfaces = ibmc
-    enabled_raid_interfaces = ibmc
-    enabled_vendor_interfaces = ibmc
-
-#. Restart the ironic conductor service::
-
-    sudo service ironic-conductor restart
-
-    # Or, for RDO:
-    sudo systemctl restart openstack-ironic-conductor
-
-Registering a node with the iBMC driver
-===========================================
-
-Nodes configured to use the driver should have the ``driver`` property
-set to ``ibmc``.
-
-The following properties are specified in the node's ``driver_info``
-field:
-
-- ``ibmc_address``:
-
-  The URL address to the ibmc controller. It must
-  include the authority portion of the URL, and can
-  optionally include the scheme. If the scheme is
-  missing, https is assumed.
-  For example: https://ibmc.example.com. This is required.
-
-- ``ibmc_username``:
-
-  User account with admin/server-profile access
-  privilege. This is required.
-
-- ``ibmc_password``:
-
-  User account password. This is required.
-
-- ``ibmc_verify_ca``:
-
-  If ibmc_address has the **https** scheme, the
-  driver will use a secure (TLS_) connection when
-  talking to the ibmc controller. By default
-  (if this is set to True), the driver will try to
-  verify the host certificates. This can be set to
-  the path of a certificate file or directory with
-  trusted certificates that the driver will use for
-  verification. To disable verifying TLS_, set this
-  to False. This is optional.
-
-The ``baremetal node create`` command can be used to enroll
-a node with the ``ibmc`` driver. For example:
-
-.. code-block:: bash
-
-  baremetal node create --driver ibmc
-    --driver-info ibmc_address=https://example.com \
-    --driver-info ibmc_username=admin \
-    --driver-info ibmc_password=password
-
-For more information about enrolling nodes see :ref:`enrollment`
-in the install guide.
-
-RAID Interface
-==============
-
-Currently, only RAID controller which supports OOB management can be managed.
-
-See :doc:`/admin/raid` for more information on Ironic RAID support.
-
-The following properties are supported by the iBMC raid interface
-implementation, ``ibmc``:
-
-Mandatory properties
---------------------
-
-* ``size_gb``: Size in gigabytes (integer) for the logical disk. Use ``MAX`` as
-  ``size_gb`` if this logical disk is supposed to use the rest of the space
-  available.
-* ``raid_level``: RAID level for the logical disk. Valid values are
-  ``JBOD``, ``0``, ``1``, ``5``, ``6``, ``1+0``, ``5+0`` and ``6+0``. And it
-  is possible that some RAID controllers can only support a subset RAID
-  levels.
-
-.. NOTE::
-  RAID level ``2`` is not supported by ``iBMC`` driver.
-
-Optional properties
--------------------
-
-* ``is_root_volume``: Optional. Specifies whether this disk is a root volume.
-  By default, this is ``False``.
-* ``volume_name``: Optional. Name of the volume to be created. If this is not
-  specified, it will be N/A.
-
-Backing physical disk hints
----------------------------
-
-See :doc:`/admin/raid` for more information on backing disk hints.
-
-These are machine-independent properties. The hints are specified for each
-logical disk to help Ironic find the desired disks for RAID configuration.
-
-* ``share_physical_disks``
-* ``disk_type``
-* ``interface_type``
-* ``number_of_physical_disks``
-
-Backing physical disks
-----------------------
-
-These are HUAWEI RAID controller dependent properties:
-
-* ``controller``: Optional. Supported values are: RAID storage id,
-  RAID storage name or RAID controller name. If a bare metal server have more
-  than one controller, this is mandatory. Typical values would look like:
-
-    * RAID Storage Id: ``RAIDStorage0``
-    * RAID Storage Name: ``RAIDStorage0``
-    * RAID Controller Name: ``RAID Card1 Controller``.
-
-* ``physical_disks``: Optional. Supported values are: disk-id, disk-name or
-  disk serial number. Typical values for hdd disk would look like:
-
-    * Disk Id: ``HDDPlaneDisk0``
-    * Disk Name: ``Disk0``.
-    * Disk SerialNumber: ``38DGK77LF77D``
-
-Delete RAID configuration
--------------------------
-
-For ``delete_configuration`` step, ``ibmc`` will do:
-
-* delete all logical disks
-* delete all hot-spare disks
-
-Logical disks creation priority
--------------------------------
-
-Logical Disks creation priority based on three properties:
-
-* ``share_physical_disks``
-* ``physical_disks``
-* ``size_gb``
-
-The logical disks creation priority strictly follow the table below, if
-multiple logical disks have the same priority, then they will be created with
-the same order in ``logical_disks`` array.
-
-====================       ==========================       =========
-Share physical disks       Specified Physical Disks         Size
-====================       ==========================       =========
-no                         yes                              int|max
-no                         no                               int
-yes                        yes                              int
-yes                        yes                              max
-yes                        no                               int
-yes                        no                               max
-no                         no                               max
-====================       ==========================       =========
-
-Physical disks choice strategy
-------------------------------
-
-.. note::
-    physical-disk-group: a group of physical disks which have been used by some
-    logical-disks with same RAID level.
-
-
-*   If no ``physical_disks`` are specified, the "waste least" strategy will be
-    used to choose the physical disks.
-
-    * waste least disk capacity: when using disks with different capacity, it
-      will cause a waste of disk capacity. This is to avoid with highest
-      priority.
-    * using least total disk capacity: for example, we can create 400G RAID 5
-      with both 5 100G-disks and 3 200G-disks. 5 100G disks is a better
-      strategy because it uses a 500G capacity totally. While 3 200G-disks
-      are 600G totally.
-    * using least disk count: finally, if waste capacity and total disk
-      capacity are both the same (it rarely happens?), we will choose the one
-      with the minimum number of disks.
-
-*   when ``share_physical_disks`` option is present, ``ibmc`` driver will
-    create logical disk upon existing physical-disk-group list first. Only
-    when no existing physical-disk-group matches, then it chooses unused
-    physical disks with same strategy described above. When multiple exists
-    physical-disk-groups matches, it will use "waste least" strategy too,
-    the bigger capacity left the better. For example, to create a logical disk
-    shown below on a ``ibmc`` server which has two RAID5 logical disks already.
-    And the shareable capacity of this two logical-disks are 500G and 300G,
-    then ``ibmc`` driver will choose the second one.
-
-    .. code-block:: json
-
-     {
-        "logical_disks": [
-            {
-                "controller": "RAID Card1 Controller",
-                "raid_level": "5",
-                "size_gb": 100,
-                "share_physical_disks": true
-            }
-        ]
-     }
-
-    And the ``ibmc`` server has two RAID5 logical disks already.
-
-*   When ``size_gb`` is set to ``MAX``, ``ibmc`` driver will auto work through
-    all possible cases and choose the "best" solution which has the biggest
-    capacity and use least capacity. For example: to create a RAID 5+0 logical
-    disk with MAX size in a server has 9 200G-disks, it will finally choose
-    "8 disks + span-number 2" but not "9 disks + span-number 3". Although they
-    both have 1200G capacity totally, but the former uses only 8 disks and the
-    latter uses 9 disks. If you want to choose the latter solution, you can
-    specified the disk count to use by adding ``number_of_physical_disks``
-    option.
-
-    .. code-block:: json
-
-     {
-        "logical_disks": [
-            {
-                "controller": "RAID Card1 Controller",
-                "raid_level": "5+0",
-                "size_gb": "MAX"
-            }
-        ]
-     }
-
-
-Examples
---------
-
-In a typical scenario we may want to create:
- * RAID 5, 500G, root OS volume with 3 disks
- * RAID 5, rest available space, data volume with rest disks
-
-.. code-block:: json
-
-  {
-    "logical_disks": [
-        {
-            "volume_name": "os_volume",
-            "controller": "RAID Card1 Controller",
-            "is_root_volume": "True",
-            "physical_disks": [
-                "Disk0",
-                "Disk1",
-                "Disk2"
-            ],
-            "raid_level": "5",
-            "size_gb": "500"
-        },
-        {
-            "volume_name": "data_volume",
-            "controller": "RAID Card1 Controller",
-            "raid_level": "5",
-            "size_gb": "MAX"
-        }
-    ]
-  }
-
-Vendor Interface
-=========================================
-
-The ``ibmc`` hardware type provides vendor passthru interfaces shown below:
-
-
-========================  ============   ======================================
-Method Name               HTTP Method    Description
-========================  ============   ======================================
-boot_up_seq               GET            Query boot up sequence
-get_raid_controller_list  GET            Query RAID controller summary info
-========================  ============   ======================================
-
-.. _Huawei iBMC: https://e.huawei.com/en/products/computing/kunpeng/accessories/ibmc
-.. _TLS: https://en.wikipedia.org/wiki/Transport_Layer_Security
-.. _HUAWEI iBMC Client library: https://pypi.org/project/python-ibmcclient/
diff --git a/driver-requirements.txt b/driver-requirements.txt
index f02e65f4ef..1b8cb28a22 100644
--- a/driver-requirements.txt
+++ b/driver-requirements.txt
@@ -14,8 +14,5 @@ python-dracclient>=5.1.0,<9.0.0
 # Ansible-deploy interface
 ansible>=2.7
 
-# HUAWEI iBMC hardware type uses the python-ibmcclient library
-python-ibmcclient>=0.2.2,<0.3.0
-
 # Dell EMC iDRAC sushy OEM extension
 sushy-oem-idrac>=5.0.0,<6.0.0
diff --git a/ironic/common/exception.py b/ironic/common/exception.py
index 1b5f0f9ae4..b838b745c1 100644
--- a/ironic/common/exception.py
+++ b/ironic/common/exception.py
@@ -720,14 +720,6 @@ class InvalidKickstartFile(Invalid):
     _msg_fmt = _("The kickstart file is not valid.")
 
 
-class IBMCError(DriverOperationError):
-    _msg_fmt = _("IBMC exception occurred on node %(node)s. Error: %(error)s")
-
-
-class IBMCConnectionError(IBMCError):
-    _msg_fmt = _("IBMC connection failed for node %(node)s: %(error)s")
-
-
 class ClientSideError(RuntimeError):
     def __init__(self, msg=None, status_code=400, faultcode='Client'):
         self.msg = msg
diff --git a/ironic/conf/__init__.py b/ironic/conf/__init__.py
index 44a04f5024..91d298a365 100644
--- a/ironic/conf/__init__.py
+++ b/ironic/conf/__init__.py
@@ -32,7 +32,6 @@ from ironic.conf import drac
 from ironic.conf import fake
 from ironic.conf import glance
 from ironic.conf import healthcheck
-from ironic.conf import ibmc
 from ironic.conf import ilo
 from ironic.conf import inspector
 from ironic.conf import inventory
@@ -69,7 +68,6 @@ dnsmasq.register_opts(CONF)
 fake.register_opts(CONF)
 glance.register_opts(CONF)
 healthcheck.register_opts(CONF)
-ibmc.register_opts(CONF)
 ilo.register_opts(CONF)
 inspector.register_opts(CONF)
 inventory.register_opts(CONF)
diff --git a/ironic/conf/ibmc.py b/ironic/conf/ibmc.py
deleted file mode 100644
index 82c5eaac75..0000000000
--- a/ironic/conf/ibmc.py
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# 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.
-
-# Version 1.0.0
-
-from oslo_config import cfg
-
-from ironic.common.i18n import _
-
-opts = [
-    cfg.IntOpt('connection_attempts',
-               min=1,
-               default=5,
-               help=_('Maximum number of attempts to try to connect '
-                      'to iBMC')),
-    cfg.IntOpt('connection_retry_interval',
-               min=1,
-               default=4,
-               help=_('Number of seconds to wait between attempts to '
-                      'connect to iBMC'))
-]
-
-
-def register_opts(conf):
-    conf.register_opts(opts, group='ibmc')
diff --git a/ironic/drivers/ibmc.py b/ironic/drivers/ibmc.py
deleted file mode 100644
index 5f37d520e5..0000000000
--- a/ironic/drivers/ibmc.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# 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.
-"""
-iBMC Driver for managing HUAWEI V5 series rack servers such as 2288H V5,
-CH121 V5.
-"""
-
-from ironic.drivers import generic
-from ironic.drivers.modules.ibmc import management as ibmc_mgmt
-from ironic.drivers.modules.ibmc import power as ibmc_power
-from ironic.drivers.modules.ibmc import raid as ibmc_raid
-from ironic.drivers.modules.ibmc import vendor as ibmc_vendor
-from ironic.drivers.modules import noop
-
-
-class IBMCHardware(generic.GenericHardware):
-    """Huawei iBMC hardware type."""
-
-    @property
-    def supported_management_interfaces(self):
-        """List of supported management interfaces."""
-        return [ibmc_mgmt.IBMCManagement]
-
-    @property
-    def supported_power_interfaces(self):
-        """List of supported power interfaces."""
-        return [ibmc_power.IBMCPower]
-
-    @property
-    def supported_vendor_interfaces(self):
-        """List of supported vendor interfaces."""
-        return [ibmc_vendor.IBMCVendor, noop.NoVendor]
-
-    @property
-    def supported_raid_interfaces(self):
-        """List of supported raid interfaces."""
-        return [ibmc_raid.IbmcRAID, noop.NoRAID]
diff --git a/ironic/drivers/modules/ibmc/management.py b/ironic/drivers/modules/ibmc/management.py
deleted file mode 100644
index b6420dc016..0000000000
--- a/ironic/drivers/modules/ibmc/management.py
+++ /dev/null
@@ -1,241 +0,0 @@
-# Copyright 2019 HUAWEI, Inc. All Rights Reserved.
-# Copyright 2017 Red Hat, Inc. All Rights Reserved.
-#
-# 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.
-"""
-iBMC Management Interface
-"""
-
-from oslo_log import log
-from oslo_utils import importutils
-
-from ironic.common import exception
-from ironic.common.i18n import _
-from ironic.conductor import task_manager
-from ironic.drivers import base
-from ironic.drivers.modules.ibmc import mappings
-from ironic.drivers.modules.ibmc import utils
-
-constants = importutils.try_import('ibmc_client.constants')
-ibmc_client = importutils.try_import('ibmc_client')
-
-LOG = log.getLogger(__name__)
-
-
-class IBMCManagement(base.ManagementInterface):
-
-    # NOTE(TheJulia): Deprecating November 2023 in favor of Redfish
-    # and due to a lack of active driver maintenance.
-    supported = False
-
-    def __init__(self):
-        """Initialize the iBMC management interface
-
-        :raises: DriverLoadError if the driver can't be loaded due to
-            missing dependencies
-        """
-        super(IBMCManagement, self).__init__()
-        if not ibmc_client:
-            raise exception.DriverLoadError(
-                driver='ibmc',
-                reason=_('Unable to import the python-ibmcclient library'))
-
-    def get_properties(self):
-        """Return the properties of the interface.
-
-        :returns: dictionary of <property name>:<property description> entries.
-        """
-        return utils.COMMON_PROPERTIES.copy()
-
-    def validate(self, task):
-        """Validates the driver information needed by the iBMC driver.
-
-        :param task: A TaskManager instance containing the node to act on.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue on missing parameter(s)
-        """
-        utils.parse_driver_info(task.node)
-
-    @utils.handle_ibmc_exception('get iBMC supported boot devices')
-    def get_supported_boot_devices(self, task):
-        """Get a list of the supported boot devices.
-
-        :param task: a task from TaskManager.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue on missing parameter(s)
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        :returns: A list with the supported boot devices defined
-                  in :mod:`ironic.common.boot_devices`.
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            system = conn.system.get()
-            boot_source_override = system.boot_source_override
-            return list(map(mappings.GET_BOOT_DEVICE_MAP.get,
-                            boot_source_override.supported_boot_devices))
-
-    @task_manager.require_exclusive_lock
-    @utils.handle_ibmc_exception('set iBMC boot device')
-    def set_boot_device(self, task, device, persistent=False):
-        """Set the boot device for a node.
-
-        :param task: A task from TaskManager.
-        :param device: The boot device, one of
-                       :mod:`ironic.common.boot_device`.
-        :param persistent: Boolean value. True if the boot device will
-                           persist to all future boots, False if not.
-                           Default: False.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue on missing parameter(s)
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            boot_device = mappings.SET_BOOT_DEVICE_MAP[device]
-            enabled = mappings.SET_BOOT_DEVICE_PERSISTENT_MAP[persistent]
-            conn.system.set_boot_source(boot_device, enabled=enabled)
-
-    @utils.handle_ibmc_exception('get iBMC boot device')
-    def get_boot_device(self, task):
-        """Get the current boot device for a node.
-
-        :param task: A task from TaskManager.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue on missing parameter(s)
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        :returns: a dictionary containing:
-
-            :boot_device:
-                the boot device, one of :mod:`ironic.common.boot_devices` or
-                None if it is unknown.
-            :persistent:
-                Boolean value or None, True if the boot device persists,
-                False otherwise. None if it's disabled.
-
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            system = conn.system.get()
-            boot_source_override = system.boot_source_override
-            boot_device = boot_source_override.target
-            enabled = boot_source_override.enabled
-            return {
-                'boot_device': mappings.GET_BOOT_DEVICE_MAP.get(boot_device),
-                'persistent':
-                    mappings.GET_BOOT_DEVICE_PERSISTENT_MAP.get(enabled)
-            }
-
-    def get_supported_boot_modes(self, task):
-        """Get a list of the supported boot modes.
-
-        :param task: A task from TaskManager.
-        :returns: A list with the supported boot modes defined
-                  in :mod:`ironic.common.boot_modes`. If boot
-                  mode support can't be determined, empty list
-                  is returned.
-        """
-        return list(mappings.SET_BOOT_MODE_MAP)
-
-    @task_manager.require_exclusive_lock
-    @utils.handle_ibmc_exception('set iBMC boot mode')
-    def set_boot_mode(self, task, mode):
-        """Set the boot mode for a node.
-
-        Set the boot mode to use on next reboot of the node.
-
-        :param task: A task from TaskManager.
-        :param mode: The boot mode, one of
-                     :mod:`ironic.common.boot_modes`.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue on missing parameter(s)
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            system = conn.system.get()
-            boot_source_override = system.boot_source_override
-            boot_device = boot_source_override.target
-            boot_override = boot_source_override.enabled
-
-            # Copied from redfish driver
-            # TODO(Qianbiao.NG) what if boot device is "NONE"?
-            if not boot_device:
-                error_msg = (_('Cannot change boot mode on node %(node)s '
-                               'because its boot device is not set.') %
-                             {'node': task.node.uuid})
-                LOG.error(error_msg)
-                raise exception.IBMCError(error_msg)
-
-            # TODO(Qianbiao.NG) what if boot override is "disabled"?
-            if not boot_override:
-                i18n = _('Cannot change boot mode on node %(node)s '
-                         'because its boot source override is not set.')
-                error_msg = i18n % {'node': task.node.uuid}
-                LOG.error(error_msg)
-                raise exception.IBMCError(error_msg)
-
-            boot_mode = mappings.SET_BOOT_MODE_MAP[mode]
-            conn.system.set_boot_source(boot_device,
-                                        enabled=boot_override,
-                                        mode=boot_mode)
-
-    @utils.handle_ibmc_exception('get iBMC boot mode')
-    def get_boot_mode(self, task):
-        """Get the current boot mode for a node.
-
-        Provides the current boot mode of the node.
-
-        :param task: A task from TaskManager.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue on missing parameter(s)
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        :returns: The boot mode, one of :mod:`ironic.common.boot_mode` or
-                  None if it is unknown.
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            system = conn.system.get()
-            boot_source_override = system.boot_source_override
-            boot_mode = boot_source_override.mode
-            return mappings.GET_BOOT_MODE_MAP.get(boot_mode)
-
-    def get_sensors_data(self, task):
-        """Get sensors data.
-
-        Not implemented for this driver.
-
-        :raises: NotImplementedError
-        """
-        raise NotImplementedError()
-
-    @task_manager.require_exclusive_lock
-    @utils.handle_ibmc_exception('inject iBMC NMI')
-    def inject_nmi(self, task):
-        """Inject NMI, Non Maskable Interrupt.
-
-        Inject NMI (Non Maskable Interrupt) for a node immediately.
-
-        :param task: A TaskManager instance containing the node to act on.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue on missing parameter(s)
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            conn.system.reset(constants.RESET_NMI)
diff --git a/ironic/drivers/modules/ibmc/mappings.py b/ironic/drivers/modules/ibmc/mappings.py
deleted file mode 100644
index e303a72ea0..0000000000
--- a/ironic/drivers/modules/ibmc/mappings.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#
-# 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.
-"""
-iBMC and Ironic constants mapping
-"""
-
-from oslo_utils import importutils
-
-from ironic.common import boot_devices
-from ironic.common import boot_modes
-from ironic.common import states
-from ironic.drivers.modules.ibmc import utils
-
-constants = importutils.try_import('ibmc_client.constants')
-
-if constants:
-    # Set power state mapping
-    SET_POWER_STATE_MAP = {
-        states.POWER_ON: constants.RESET_ON,
-        states.POWER_OFF: constants.RESET_FORCE_OFF,
-        states.REBOOT: constants.RESET_FORCE_RESTART,
-        states.SOFT_REBOOT: constants.RESET_FORCE_POWER_CYCLE,
-        states.SOFT_POWER_OFF: constants.RESET_GRACEFUL_SHUTDOWN,
-    }
-
-    # Get power state mapping
-    GET_POWER_STATE_MAP = {
-        constants.SYSTEM_POWER_STATE_ON: states.POWER_ON,
-        constants.SYSTEM_POWER_STATE_OFF: states.POWER_OFF,
-    }
-
-    # Boot device mapping
-    GET_BOOT_DEVICE_MAP = {
-        constants.BOOT_SOURCE_TARGET_NONE: 'none',
-        constants.BOOT_SOURCE_TARGET_PXE: boot_devices.PXE,
-        constants.BOOT_SOURCE_TARGET_FLOPPY: 'floppy',
-        constants.BOOT_SOURCE_TARGET_CD: boot_devices.CDROM,
-        constants.BOOT_SOURCE_TARGET_HDD: boot_devices.DISK,
-        constants.BOOT_SOURCE_TARGET_BIOS_SETUP: boot_devices.BIOS,
-    }
-
-    SET_BOOT_DEVICE_MAP = utils.revert_dictionary(GET_BOOT_DEVICE_MAP)
-
-    # Boot mode mapping
-    GET_BOOT_MODE_MAP = {
-        constants.BOOT_SOURCE_MODE_BIOS: boot_modes.LEGACY_BIOS,
-        constants.BOOT_SOURCE_MODE_UEFI: boot_modes.UEFI,
-    }
-
-    SET_BOOT_MODE_MAP = utils.revert_dictionary(GET_BOOT_MODE_MAP)
-
-    # Boot device persistent mapping
-    GET_BOOT_DEVICE_PERSISTENT_MAP = {
-        constants.BOOT_SOURCE_ENABLED_ONCE: False,
-        constants.BOOT_SOURCE_ENABLED_CONTINUOUS: True,
-        constants.BOOT_SOURCE_ENABLED_DISABLED: None,
-    }
-
-    SET_BOOT_DEVICE_PERSISTENT_MAP = utils.revert_dictionary(
-        GET_BOOT_DEVICE_PERSISTENT_MAP)
diff --git a/ironic/drivers/modules/ibmc/power.py b/ironic/drivers/modules/ibmc/power.py
deleted file mode 100644
index 9c2e2b4acd..0000000000
--- a/ironic/drivers/modules/ibmc/power.py
+++ /dev/null
@@ -1,149 +0,0 @@
-#
-# 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.
-"""
-iBMC Power Interface
-"""
-
-from oslo_log import log
-from oslo_utils import importutils
-
-from ironic.common import exception
-from ironic.common.i18n import _
-from ironic.common import states
-from ironic.conductor import task_manager
-from ironic.conductor import utils as cond_utils
-from ironic.drivers import base
-from ironic.drivers.modules.ibmc import mappings
-from ironic.drivers.modules.ibmc import utils
-
-constants = importutils.try_import('ibmc_client.constants')
-ibmc_client = importutils.try_import('ibmc_client')
-
-LOG = log.getLogger(__name__)
-
-EXPECT_POWER_STATE_MAP = {
-    states.REBOOT: states.POWER_ON,
-    states.SOFT_REBOOT: states.POWER_ON,
-    states.SOFT_POWER_OFF: states.POWER_OFF,
-}
-
-
-class IBMCPower(base.PowerInterface):
-
-    # NOTE(TheJulia): Deprecating November 2023 in favor of Redfish
-    # and due to a lack of active driver maintenance.
-    supported = False
-
-    def __init__(self):
-        """Initialize the iBMC power interface.
-
-        :raises: DriverLoadError if the driver can't be loaded due to
-            missing dependencies
-        """
-        super(IBMCPower, self).__init__()
-        if not ibmc_client:
-            raise exception.DriverLoadError(
-                driver='ibmc',
-                reason=_('Unable to import the python-ibmcclient library'))
-
-    def get_properties(self):
-        """Return the properties of the interface.
-
-        :returns: dictionary of <property name>:<property description> entries.
-        """
-        return utils.COMMON_PROPERTIES.copy()
-
-    def validate(self, task):
-        """Validates the driver information needed by the iBMC driver.
-
-        :param task: A TaskManager instance containing the node to act on.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue on missing parameter(s)
-        """
-        utils.parse_driver_info(task.node)
-
-    @utils.handle_ibmc_exception('get iBMC power state')
-    def get_power_state(self, task):
-        """Get the current power state of the task's node.
-
-        :param task: A TaskManager instance containing the node to act on.
-        :returns: A power state. One of :mod:`ironic.common.states`.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue on missing parameter(s)
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            system = conn.system.get()
-            return mappings.GET_POWER_STATE_MAP.get(system.power_state)
-
-    @task_manager.require_exclusive_lock
-    @utils.handle_ibmc_exception('set iBMC power state')
-    def set_power_state(self, task, power_state, timeout=None):
-        """Set the power state of the task's node.
-
-        :param task: A TaskManager instance containing the node to act on.
-        :param power_state: Any power state from :mod:`ironic.common.states`.
-        :param timeout: Time to wait for the node to reach the requested state.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue if a required parameter is missing.
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            reset_type = mappings.SET_POWER_STATE_MAP.get(power_state)
-            conn.system.reset(reset_type)
-
-        target_state = EXPECT_POWER_STATE_MAP.get(power_state, power_state)
-        cond_utils.node_wait_for_power_state(task, target_state,
-                                             timeout=timeout)
-
-    @task_manager.require_exclusive_lock
-    @utils.handle_ibmc_exception('reboot iBMC')
-    def reboot(self, task, timeout=None):
-        """Perform a hard reboot of the task's node.
-
-        :param task: A TaskManager instance containing the node to act on.
-        :param timeout: Time to wait for the node to become powered on.
-        :raises: InvalidParameterValue on malformed parameter(s)
-        :raises: MissingParameterValue if a required parameter is missing.
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            system = conn.system.get()
-            current_power_state = (
-                mappings.GET_POWER_STATE_MAP.get(system.power_state)
-            )
-            if current_power_state == states.POWER_ON:
-                conn.system.reset(
-                    mappings.SET_POWER_STATE_MAP.get(states.REBOOT))
-            else:
-                conn.system.reset(
-                    mappings.SET_POWER_STATE_MAP.get(states.POWER_ON))
-
-        cond_utils.node_wait_for_power_state(task, states.POWER_ON,
-                                             timeout=timeout)
-
-    def get_supported_power_states(self, task):
-        """Get a list of the supported power states.
-
-        :param task: A TaskManager instance containing the node to act on.
-            Not used by this driver at the moment.
-        :returns: A list with the supported power states defined
-                  in :mod:`ironic.common.states`.
-        """
-        return list(mappings.SET_POWER_STATE_MAP)
diff --git a/ironic/drivers/modules/ibmc/raid.py b/ironic/drivers/modules/ibmc/raid.py
deleted file mode 100644
index bc0ee1623f..0000000000
--- a/ironic/drivers/modules/ibmc/raid.py
+++ /dev/null
@@ -1,203 +0,0 @@
-# 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.
-
-"""
-iBMC RAID configuration specific methods
-"""
-
-from ironic_lib import metrics_utils
-from oslo_log import log as logging
-from oslo_utils import importutils
-
-from ironic.common.i18n import _
-from ironic.common import raid
-from ironic import conf
-from ironic.drivers import base
-from ironic.drivers.modules.ibmc import utils
-
-constants = importutils.try_import('ibmc_client.constants')
-ibmc_client = importutils.try_import('ibmc_client')
-ibmc_error = importutils.try_import('ibmc_client.exceptions')
-
-CONF = conf.CONF
-LOG = logging.getLogger(__name__)
-METRICS = metrics_utils.get_metrics_logger(__name__)
-
-
-class IbmcRAID(base.RAIDInterface):
-    """Implementation of RAIDInterface for iBMC."""
-
-    # NOTE(TheJulia): Deprecating November 2023 in favor of Redfish
-    # and due to a lack of active driver maintenance.
-    supported = False
-
-    RAID_APPLY_CONFIGURATION_ARGSINFO = {
-        "raid_config": {
-            "description": "The RAID configuration to apply.",
-            "required": True,
-        },
-        "create_root_volume": {
-            "description": (
-                "Setting this to 'False' indicates not to create root "
-                "volume that is specified in 'raid_config'. Default "
-                "value is 'True'."
-            ),
-            "required": False,
-        },
-        "create_nonroot_volumes": {
-            "description": (
-                "Setting this to 'False' indicates not to create "
-                "non-root volumes (all except the root volume) in "
-                "'raid_config'. Default value is 'True'."
-            ),
-            "required": False,
-        },
-        "delete_existing": {
-            "description": (
-                "Setting this to 'True' indicates to delete existing RAID "
-                "configuration prior to creating the new configuration. "
-                "Default value is 'True'."
-            ),
-            "required": False,
-        }
-    }
-
-    def get_properties(self):
-        """Return the properties of the interface.
-
-        :returns: dictionary of <property name>:<property description> entries.
-        """
-        return utils.COMMON_PROPERTIES.copy()
-
-    @utils.handle_ibmc_exception('delete iBMC RAID configuration')
-    def _delete_raid_configuration(self, task):
-        """Delete the RAID configuration through `python-ibmcclient` lib.
-
-        :param task: a TaskManager instance containing the node to act on.
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            # NOTE(qianbiao.ng): To reduce review workload, we should keep all
-            # delete logic in python-ibmcclient. And delete raid configuration
-            # logic should be synchronized. if async required, do it in
-            # python-ibmcclient.
-            conn.system.storage.delete_all_raid_configuration()
-
-    @utils.handle_ibmc_exception('create iBMC RAID configuration')
-    def _create_raid_configuration(self, task, logical_disks):
-        """Create the RAID configuration through `python-ibmcclient` lib.
-
-        :param task: a TaskManager instance containing the node to act on.
-        :param logical_disks: a list of JSON dictionaries which represents
-            the logical disks to be created. The JSON dictionary should match
-            the (ironic.drivers.raid_config_schema.json) scheme.
-        """
-        ibmc = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**ibmc) as conn:
-            # NOTE(qianbiao.ng): To reduce review workload, we should keep all
-            # apply logic in python-ibmcclient. And apply raid configuration
-            # logic should be synchronized. if async required, do it in
-            # python-ibmcclient.
-            conn.system.storage.apply_raid_configuration(logical_disks)
-
-    @base.deploy_step(priority=0,
-                      argsinfo=RAID_APPLY_CONFIGURATION_ARGSINFO)
-    def apply_configuration(self, task, raid_config, create_root_volume=True,
-                            create_nonroot_volumes=False):
-        return super(IbmcRAID, self).apply_configuration(
-            task, raid_config, create_root_volume=create_root_volume,
-            create_nonroot_volumes=create_nonroot_volumes)
-
-    @METRICS.timer('IbmcRAID.create_configuration')
-    @base.clean_step(priority=0, abortable=False, argsinfo={
-        'create_root_volume': {
-            'description': ('This specifies whether to create the root '
-                            'volume. Defaults to `True`.'),
-            'required': False
-        },
-        'create_nonroot_volumes': {
-            'description': ('This specifies whether to create the non-root '
-                            'volumes. Defaults to `True`.'),
-            'required': False
-        },
-        "delete_existing": {
-            "description": ("Setting this to 'True' indicates to delete "
-                            "existing RAID configuration prior to creating "
-                            "the new configuration. "
-                            "Default value is 'False'."),
-            "required": False,
-        }
-    })
-    def create_configuration(self, task, create_root_volume=True,
-                             create_nonroot_volumes=True,
-                             delete_existing=False):
-        """Create a RAID configuration.
-
-        This method creates a RAID configuration on the given node.
-
-        :param task: a TaskManager instance.
-        :param create_root_volume: If True, a root volume is created
-            during RAID configuration. Otherwise, no root volume is
-            created. Default is True.
-        :param create_nonroot_volumes: If True, non-root volumes are
-            created. If False, no non-root volumes are created. Default
-            is True.
-        :param delete_existing: Setting this to True indicates to delete RAID
-            configuration prior to creating the new configuration. Default is
-            False.
-        :raises: MissingParameterValue, if node.target_raid_config is missing
-            or empty after skipping root volume and/or non-root volumes.
-        :raises: IBMCError, on failure to execute step.
-        """
-        node = task.node
-        raid_config = raid.filter_target_raid_config(
-            node, create_root_volume=create_root_volume,
-            create_nonroot_volumes=create_nonroot_volumes)
-        LOG.info(_("Invoke RAID create_configuration step for node %s(uuid). "
-                   "Current provision state is: %(status)s. "
-                   "Target RAID configuration is: %(config)s."),
-                 {'uuid': node.uuid, 'status': node.provision_state,
-                  'target': raid_config})
-
-        # cache current raid config to node's driver_internal_info
-        node.driver_internal_info['raid_config'] = raid_config
-        node.save()
-
-        # delete exist volumes if necessary
-        if delete_existing:
-            self._delete_raid_configuration(task)
-
-        # create raid configuration
-        logical_disks = raid_config.get('logical_disks', [])
-        self._create_raid_configuration(task, logical_disks)
-        LOG.info(_("Succeed to create raid configuration on node %s."),
-                 task.node.uuid)
-
-    @METRICS.timer('IbmcRAID.delete_configuration')
-    @base.clean_step(priority=0, abortable=False)
-    @base.deploy_step(priority=0)
-    def delete_configuration(self, task):
-        """Delete the RAID configuration.
-
-        :param task: a TaskManager instance containing the node to act on.
-        :returns: states.CLEANWAIT if cleaning operation in progress
-            asynchronously or states.DEPLOYWAIT if deploy operation in
-            progress synchronously or None if it is completed.
-        :raises: IBMCError, on failure to execute step.
-        """
-        node = task.node
-        LOG.info("Invoke RAID delete_configuration step for node %s(uuid). "
-                 "Current provision state is: %(status)s. ",
-                 {'uuid': node.uuid, 'status': node.provision_state})
-        self._delete_raid_configuration(task)
-        LOG.info(_("Succeed to delete raid configuration on node %s."),
-                 task.node.uuid)
diff --git a/ironic/drivers/modules/ibmc/utils.py b/ironic/drivers/modules/ibmc/utils.py
deleted file mode 100644
index 44113c0fe4..0000000000
--- a/ironic/drivers/modules/ibmc/utils.py
+++ /dev/null
@@ -1,172 +0,0 @@
-#
-# 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.
-"""
-iBMC Driver common utils
-"""
-
-import functools
-import os
-
-from oslo_log import log
-from oslo_utils import importutils
-from oslo_utils import netutils
-from oslo_utils import strutils
-import tenacity
-
-from ironic.common import exception
-from ironic.common.i18n import _
-from ironic.conductor import task_manager
-from ironic.conf import CONF
-
-ibmc_client = importutils.try_import('ibmcclient')
-ibmc_error = importutils.try_import('ibmc_client.exceptions')
-
-LOG = log.getLogger(__name__)
-
-REQUIRED_PROPERTIES = {
-    'ibmc_address': _('The URL address to the iBMC controller. It must '
-                      'include the authority portion of the URL. '
-                      'If the scheme is missing, https is assumed. '
-                      'For example: https://mgmt.vendor.com. Required.'),
-    'ibmc_username': _('User account with admin/server-profile access '
-                       'privilege. Required.'),
-    'ibmc_password': _('User account password. Required.'),
-}
-
-OPTIONAL_PROPERTIES = {
-    'ibmc_verify_ca': _('Either a Boolean value, a path to a CA_BUNDLE '
-                        'file or directory with certificates of trusted '
-                        'CAs. If set to True the driver will verify the '
-                        'host certificates; if False the driver will '
-                        'ignore verifying the SSL certificate. If it\'s '
-                        'a path the driver will use the specified '
-                        'certificate or one of the certificates in the '
-                        'directory. Defaults to True. Optional.'),
-}
-
-COMMON_PROPERTIES = REQUIRED_PROPERTIES.copy()
-COMMON_PROPERTIES.update(OPTIONAL_PROPERTIES)
-
-
-def parse_driver_info(node):
-    """Parse the information required for Ironic to connect to iBMC.
-
-    :param node: an Ironic node object
-    :returns: dictionary of parameters
-    :raises: InvalidParameterValue on malformed parameter(s)
-    :raises: MissingParameterValue on missing parameter(s)
-    """
-    driver_info = node.driver_info or {}
-    missing_info = [key for key in REQUIRED_PROPERTIES
-                    if not driver_info.get(key)]
-    if missing_info:
-        raise exception.MissingParameterValue(_(
-            'Missing the following iBMC properties in node '
-            '%(node)s driver_info: %(info)s') % {'node': node.uuid,
-                                                 'info': missing_info})
-
-    # Validate the iBMC address
-    address = driver_info['ibmc_address']
-    if '://' not in address:
-        address = 'https://%s' % address
-
-    parsed = netutils.urlsplit(address)
-    if not parsed.netloc:
-        raise exception.InvalidParameterValue(
-            _('Invalid iBMC address %(address)s set in '
-              'driver_info/ibmc_address on node %(node)s') %
-            {'address': address, 'node': node.uuid})
-
-    # Check if verify_ca is a Boolean or a file/directory in the file-system
-    verify_ca = driver_info.get('ibmc_verify_ca', True)
-    if isinstance(verify_ca, str):
-        if not os.path.exists(verify_ca):
-            try:
-                verify_ca = strutils.bool_from_string(verify_ca, strict=True)
-            except ValueError:
-                raise exception.InvalidParameterValue(
-                    _('Invalid value type set in driver_info/'
-                      'ibmc_verify_ca on node %(node)s. '
-                      'The value should be a Boolean or the path '
-                      'to a file/directory, not "%(value)s"'
-                      ) % {'value': verify_ca, 'node': node.uuid})
-    elif not isinstance(verify_ca, bool):
-        raise exception.InvalidParameterValue(
-            _('Invalid value type set in driver_info/ibmc_verify_ca '
-              'on node %(node)s. The value should be a Boolean or the path '
-              'to a file/directory, not "%(value)s"') % {'value': verify_ca,
-                                                         'node': node.uuid})
-    return {'address': address,
-            'username': driver_info.get('ibmc_username'),
-            'password': driver_info.get('ibmc_password'),
-            'verify_ca': verify_ca}
-
-
-def revert_dictionary(d):
-    return {v: k for k, v in d.items()}
-
-
-def handle_ibmc_exception(action):
-    """Decorator to handle iBMC client exception.
-
-    Decorated functions must take a :class:`TaskManager` as the first
-    parameter.
-    """
-
-    def decorator(f):
-
-        def should_retry(e):
-            connect_error = isinstance(e, exception.IBMCConnectionError)
-            if connect_error:
-                LOG.info(_('Failed to connect to iBMC, will retry now. '
-                           'Max retry times is %(retry_times)d.'),
-                         {'retry_times': CONF.ibmc.connection_attempts})
-            return connect_error
-
-        @tenacity.retry(
-            retry=tenacity.retry_if_exception(should_retry),
-            stop=tenacity.stop_after_attempt(CONF.ibmc.connection_attempts),
-            wait=tenacity.wait_fixed(CONF.ibmc.connection_retry_interval),
-            reraise=True)
-        @functools.wraps(f)
-        def wrapper(*args, **kwargs):
-            # NOTE(dtantsur): this code could be written simpler, but then unit
-            # testing decorated functions is pretty hard, as we usually pass a
-            # Mock object instead of TaskManager there.
-            if len(args) > 1:
-                is_task_mgr = isinstance(args[1], task_manager.TaskManager)
-                task = args[1] if is_task_mgr else args[0]
-            else:
-                task = args[0]
-
-            node = task.node
-
-            try:
-                return f(*args, **kwargs)
-            except ibmc_error.IBMCConnectionError as e:
-                error = (_('Failed to connect to iBMC for node %(node)s, '
-                           'Error: %(error)s')
-                         % {'node': node.uuid, 'error': e})
-                LOG.error(error)
-                raise exception.IBMCConnectionError(node=node.uuid,
-                                                    error=error)
-            except ibmc_error.IBMCClientError as e:
-                error = (_('Failed to %(action)s for node %(node)s, '
-                           'Error %(error)s')
-                         % {'node': node.uuid, 'action': action, 'error': e})
-                LOG.error(error)
-                raise exception.IBMCError(node=node.uuid, error=error)
-
-        return wrapper
-
-    return decorator
diff --git a/ironic/drivers/modules/ibmc/vendor.py b/ironic/drivers/modules/ibmc/vendor.py
deleted file mode 100644
index dcdb8f8394..0000000000
--- a/ironic/drivers/modules/ibmc/vendor.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#
-# 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.
-"""
-iBMC Vendor Interface
-"""
-
-from oslo_log import log
-from oslo_utils import importutils
-
-from ironic.common import exception
-from ironic.common.i18n import _
-from ironic.drivers import base
-from ironic.drivers.modules.ibmc import utils
-
-ibmc_client = importutils.try_import('ibmc_client')
-
-LOG = log.getLogger(__name__)
-
-
-class IBMCVendor(base.VendorInterface):
-
-    # NOTE(TheJulia): Deprecating November 2023 in favor of Redfish
-    # and due to a lack of active driver maintenance.
-    supported = False
-
-    def __init__(self):
-        """Initialize the iBMC vendor interface.
-
-        :raises: DriverLoadError if the driver can't be loaded due to
-            missing dependencies
-        """
-        super(IBMCVendor, self).__init__()
-        if not ibmc_client:
-            raise exception.DriverLoadError(
-                driver='ibmc',
-                reason=_('Unable to import the python-ibmcclient library'))
-
-    def validate(self, task, method=None, **kwargs):
-        """Validate vendor-specific actions.
-
-        If invalid, raises an exception; otherwise returns None.
-
-        :param task: A task from TaskManager.
-        :param method: Method to be validated
-        :param kwargs: Info for action.
-        :raises: UnsupportedDriverExtension if 'method' can not be mapped to
-                 the supported interfaces.
-        :raises: InvalidParameterValue if kwargs does not contain 'method'.
-        :raises: MissingParameterValue
-        """
-        utils.parse_driver_info(task.node)
-
-    def get_properties(self):
-        """Return the properties of the interface.
-
-        :returns: dictionary of <property name>:<property description> entries.
-        """
-        return utils.COMMON_PROPERTIES.copy()
-
-    @base.passthru(['GET'], async_call=False,
-                   description=_('Returns a dictionary, '
-                                 'containing node boot up sequence, '
-                                 'in ascending order'))
-    @utils.handle_ibmc_exception('get iBMC boot up sequence')
-    def boot_up_seq(self, task, **kwargs):
-        """List boot type order of the node.
-
-        :param task: A TaskManager instance containing the node to act on.
-        :param kwargs: Not used.
-        :raises: InvalidParameterValue if kwargs does not contain 'method'.
-        :raises: MissingParameterValue
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        :returns: A dictionary, containing node boot up sequence,
-                in ascending order.
-        """
-        driver_info = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**driver_info) as conn:
-            system = conn.system.get()
-            boot_sequence = system.boot_sequence
-            return {'boot_up_sequence': boot_sequence}
-
-    @base.passthru(['GET'], async_call=False,
-                   description=_('Returns a list of dictionary, every '
-                                 'dictionary represents a RAID controller '
-                                 'summary info'))
-    @utils.handle_ibmc_exception('get iBMC RAID controller summary')
-    def get_raid_controller_list(self, task, **kwargs):
-        """List RAID controllers summary info of the node.
-
-        :param task: A TaskManager instance containing the node to act on.
-        :param kwargs: Not used.
-        :raises: IBMCConnectionError when it fails to connect to iBMC
-        :raises: IBMCError when iBMC responses an error information
-        :returns: A list of dictionaries, every dictionary represents a RAID
-            controller summary of node.
-        """
-        driver_info = utils.parse_driver_info(task.node)
-        with ibmc_client.connect(**driver_info) as conn:
-            controllers = conn.system.storage.list()
-            summaries = [ctrl.summary() for ctrl in controllers]
-            return summaries
diff --git a/ironic/tests/unit/db/utils.py b/ironic/tests/unit/db/utils.py
index e9f287c92c..33e9601609 100644
--- a/ironic/tests/unit/db/utils.py
+++ b/ironic/tests/unit/db/utils.py
@@ -679,15 +679,6 @@ def create_test_deploy_template(**kw):
     return dbapi.create_deploy_template(template)
 
 
-def get_test_ibmc_info():
-    return {
-        "ibmc_address": "https://example.com",
-        "ibmc_username": "username",
-        "ibmc_password": "password",
-        "verify_ca": False,
-    }
-
-
 def get_test_history(**kw):
     return {
         'id': kw.get('id', 345),
diff --git a/ironic/tests/unit/drivers/modules/ibmc/base.py b/ironic/tests/unit/drivers/modules/ibmc/base.py
deleted file mode 100644
index 9a282b1cb2..0000000000
--- a/ironic/tests/unit/drivers/modules/ibmc/base.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# 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.
-"""Test base class for iBMC Driver."""
-
-from unittest import mock
-
-from ironic.drivers.modules.ibmc import utils
-from ironic.tests.unit.db import base as db_base
-from ironic.tests.unit.db import utils as db_utils
-from ironic.tests.unit.objects import utils as obj_utils
-
-
-class IBMCTestCase(db_base.DbTestCase):
-
-    def setUp(self):
-        super(IBMCTestCase, self).setUp()
-        self.driver_info = db_utils.get_test_ibmc_info()
-        self.config(enabled_hardware_types=['ibmc'],
-                    enabled_power_interfaces=['ibmc'],
-                    enabled_management_interfaces=['ibmc'],
-                    enabled_vendor_interfaces=['ibmc'],
-                    enabled_raid_interfaces=['ibmc'])
-        self.node = obj_utils.create_test_node(
-            self.context, driver='ibmc', driver_info=self.driver_info)
-        self.ibmc = utils.parse_driver_info(self.node)
-
-    @staticmethod
-    def mock_ibmc_conn(ibmc_client_connect):
-        conn = mock.Mock(system=mock.PropertyMock())
-        conn.__enter__ = mock.Mock(return_value=conn)
-        conn.__exit__ = mock.Mock(return_value=None)
-        ibmc_client_connect.return_value = conn
-        return conn
diff --git a/ironic/tests/unit/drivers/modules/ibmc/test_management.py b/ironic/tests/unit/drivers/modules/ibmc/test_management.py
deleted file mode 100644
index db6b0f7e64..0000000000
--- a/ironic/tests/unit/drivers/modules/ibmc/test_management.py
+++ /dev/null
@@ -1,294 +0,0 @@
-#
-# 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.
-"""Test class for iBMC Management interface."""
-
-import itertools
-from unittest import mock
-
-from oslo_utils import importutils
-
-from ironic.common import boot_devices
-from ironic.common import boot_modes
-from ironic.common import exception
-from ironic.conductor import task_manager
-from ironic.drivers.modules.ibmc import mappings
-from ironic.drivers.modules.ibmc import utils
-from ironic.tests.unit.drivers.modules.ibmc import base
-
-constants = importutils.try_import('ibmc_client.constants')
-ibmc_client = importutils.try_import('ibmc_client')
-ibmc_error = importutils.try_import('ibmc_client.exceptions')
-
-
-class IBMCManagementTestCase(base.IBMCTestCase):
-
-    def test_get_properties(self):
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            properties = task.driver.get_properties()
-            for prop in utils.COMMON_PROPERTIES:
-                self.assertIn(prop, properties)
-
-    @mock.patch.object(utils, 'parse_driver_info', autospec=True)
-    def test_validate(self, mock_parse_driver_info):
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            task.driver.management.validate(task)
-            mock_parse_driver_info.assert_called_once_with(task.node)
-
-    def test_get_supported_boot_devices(self):
-        if not mock._is_instance_mock(ibmc_client):
-            mock.patch.object(ibmc_client, 'connect', autospec=True).start()
-        connect_ibmc = ibmc_client.connect
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        # mock return value
-        _supported_boot_devices = list(mappings.GET_BOOT_DEVICE_MAP)
-        conn.system.get.return_value = mock.Mock(
-            boot_source_override=mock.Mock(
-                supported_boot_devices=_supported_boot_devices
-            )
-        )
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            supported_boot_devices = (
-                task.driver.management.get_supported_boot_devices(task))
-            connect_ibmc.assert_called_with(**self.ibmc)
-            expect = sorted(list(mappings.GET_BOOT_DEVICE_MAP.values()))
-            self.assertEqual(expect, sorted(supported_boot_devices))
-
-    def test_set_boot_device(self):
-        if not mock._is_instance_mock(ibmc_client):
-            mock.patch.object(ibmc_client, 'connect', autospec=True).start()
-        connect_ibmc = ibmc_client.connect
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        # mock return value
-        conn.system.set_boot_source.return_value = None
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            device_mapping = [
-                (boot_devices.PXE, constants.BOOT_SOURCE_TARGET_PXE),
-                (boot_devices.DISK, constants.BOOT_SOURCE_TARGET_HDD),
-                (boot_devices.CDROM, constants.BOOT_SOURCE_TARGET_CD),
-                (boot_devices.BIOS,
-                 constants.BOOT_SOURCE_TARGET_BIOS_SETUP),
-                ('floppy', constants.BOOT_SOURCE_TARGET_FLOPPY),
-            ]
-
-            persistent_mapping = [
-                (True, constants.BOOT_SOURCE_ENABLED_CONTINUOUS),
-                (False, constants.BOOT_SOURCE_ENABLED_ONCE)
-            ]
-
-            data_source = list(itertools.product(device_mapping,
-                                                 persistent_mapping))
-            for (device, persistent) in data_source:
-                task.driver.management.set_boot_device(
-                    task, device[0], persistent=persistent[0])
-                connect_ibmc.assert_called_with(**self.ibmc)
-                conn.system.set_boot_source.assert_called_once_with(
-                    device[1],
-                    enabled=persistent[1])
-                # Reset mocks
-                connect_ibmc.reset_mock()
-                conn.system.set_boot_source.reset_mock()
-
-    def test_set_boot_device_fail(self):
-        if not mock._is_instance_mock(ibmc_client):
-            mock.patch.object(ibmc_client, 'connect', autospec=True).start()
-        connect_ibmc = ibmc_client.connect
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        # mock return value
-        conn.system.set_boot_source.side_effect = (
-            ibmc_error.IBMCClientError
-        )
-
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            self.assertRaisesRegex(
-                exception.IBMCError, 'set iBMC boot device',
-                task.driver.management.set_boot_device, task,
-                boot_devices.PXE)
-            connect_ibmc.assert_called_with(**self.ibmc)
-            conn.system.set_boot_source.assert_called_once_with(
-                constants.BOOT_SOURCE_TARGET_PXE,
-                enabled=constants.BOOT_SOURCE_ENABLED_ONCE)
-
-    def test_get_boot_device(self):
-        if not mock._is_instance_mock(ibmc_client):
-            mock.patch.object(ibmc_client, 'connect', autospec=True).start()
-        connect_ibmc = ibmc_client.connect
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        # mock return value
-        conn.system.get.return_value = mock.Mock(
-            boot_source_override=mock.Mock(
-                target=constants.BOOT_SOURCE_TARGET_PXE,
-                enabled=constants.BOOT_SOURCE_ENABLED_CONTINUOUS
-            )
-        )
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            result_boot_device = task.driver.management.get_boot_device(task)
-            conn.system.get.assert_called_once()
-            connect_ibmc.assert_called_once_with(**self.ibmc)
-            expected = {'boot_device': boot_devices.PXE,
-                        'persistent': True}
-            self.assertEqual(expected, result_boot_device)
-
-    def test_get_supported_boot_modes(self):
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            supported_boot_modes = (
-                task.driver.management.get_supported_boot_modes(task))
-            self.assertEqual(list(mappings.SET_BOOT_MODE_MAP),
-                             supported_boot_modes)
-
-    def test_set_boot_mode(self):
-        if not mock._is_instance_mock(ibmc_client):
-            mock.patch.object(ibmc_client, 'connect', autospec=True).start()
-        connect_ibmc = ibmc_client.connect
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        # mock system boot source override return value
-        conn.system.get.return_value = mock.Mock(
-            boot_source_override=mock.Mock(
-                target=constants.BOOT_SOURCE_TARGET_PXE,
-                enabled=constants.BOOT_SOURCE_ENABLED_CONTINUOUS
-            )
-        )
-        conn.system.set_boot_source.return_value = None
-
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            expected_values = [
-                (boot_modes.LEGACY_BIOS, constants.BOOT_SOURCE_MODE_BIOS),
-                (boot_modes.UEFI, constants.BOOT_SOURCE_MODE_UEFI)
-            ]
-
-            for ironic_boot_mode, ibmc_boot_mode in expected_values:
-                task.driver.management.set_boot_mode(task,
-                                                     mode=ironic_boot_mode)
-
-                conn.system.get.assert_called_once()
-                connect_ibmc.assert_called_with(**self.ibmc)
-
-                conn.system.set_boot_source.assert_called_once_with(
-                    constants.BOOT_SOURCE_TARGET_PXE,
-                    enabled=constants.BOOT_SOURCE_ENABLED_CONTINUOUS,
-                    mode=ibmc_boot_mode)
-
-                # Reset
-                connect_ibmc.reset_mock()
-                conn.system.set_boot_source.reset_mock()
-                conn.system.get.reset_mock()
-
-    def test_set_boot_mode_fail(self):
-        if not mock._is_instance_mock(ibmc_client):
-            mock.patch.object(ibmc_client, 'connect', autospec=True).start()
-        connect_ibmc = ibmc_client.connect
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        # mock system boot source override return value
-        conn.system.get.return_value = mock.Mock(
-            boot_source_override=mock.Mock(
-                target=constants.BOOT_SOURCE_TARGET_PXE,
-                enabled=constants.BOOT_SOURCE_ENABLED_CONTINUOUS
-            )
-        )
-        conn.system.set_boot_source.side_effect = (
-            ibmc_error.IBMCClientError
-        )
-
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            expected_values = [
-                (boot_modes.LEGACY_BIOS, constants.BOOT_SOURCE_MODE_BIOS),
-                (boot_modes.UEFI, constants.BOOT_SOURCE_MODE_UEFI)
-            ]
-
-            for ironic_boot_mode, ibmc_boot_mode in expected_values:
-                self.assertRaisesRegex(
-                    exception.IBMCError, 'set iBMC boot mode',
-                    task.driver.management.set_boot_mode, task,
-                    ironic_boot_mode)
-
-                conn.system.set_boot_source.assert_called_once_with(
-                    constants.BOOT_SOURCE_TARGET_PXE,
-                    enabled=constants.BOOT_SOURCE_ENABLED_CONTINUOUS,
-                    mode=ibmc_boot_mode)
-
-                conn.system.get.assert_called_once()
-                connect_ibmc.assert_called_with(**self.ibmc)
-
-                # Reset
-                connect_ibmc.reset_mock()
-                conn.system.set_boot_source.reset_mock()
-                conn.system.get.reset_mock()
-
-    def test_get_boot_mode(self):
-        if not mock._is_instance_mock(ibmc_client):
-            mock.patch.object(ibmc_client, 'connect', autospec=True).start()
-        connect_ibmc = ibmc_client.connect
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        # mock system boot source override return value
-        conn.system.get.return_value = mock.Mock(
-            boot_source_override=mock.Mock(
-                target=constants.BOOT_SOURCE_TARGET_PXE,
-                enabled=constants.BOOT_SOURCE_ENABLED_CONTINUOUS,
-                mode=constants.BOOT_SOURCE_MODE_BIOS,
-            )
-        )
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            response = task.driver.management.get_boot_mode(task)
-
-            conn.system.get.assert_called_once()
-            connect_ibmc.assert_called_with(**self.ibmc)
-
-            expected = boot_modes.LEGACY_BIOS
-            self.assertEqual(expected, response)
-
-    def test_get_sensors_data(self):
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            self.assertRaises(NotImplementedError,
-                              task.driver.management.get_sensors_data, task)
-
-    def test_inject_nmi(self):
-        if not mock._is_instance_mock(ibmc_client):
-            mock.patch.object(ibmc_client, 'connect', autospec=True).start()
-        connect_ibmc = ibmc_client.connect
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        # mock system boot source override return value
-        conn.system.reset.return_value = None
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            task.driver.management.inject_nmi(task)
-
-            connect_ibmc.assert_called_with(**self.ibmc)
-            conn.system.reset.assert_called_once_with(constants.RESET_NMI)
-
-    def test_inject_nmi_fail(self):
-        if not mock._is_instance_mock(ibmc_client):
-            mock.patch.object(ibmc_client, 'connect', autospec=True).start()
-        connect_ibmc = ibmc_client.connect
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        # mock system boot source override return value
-        conn.system.reset.side_effect = (
-            ibmc_error.IBMCClientError
-        )
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            self.assertRaisesRegex(
-                exception.IBMCError, 'inject iBMC NMI',
-                task.driver.management.inject_nmi, task)
-
-            connect_ibmc.assert_called_with(**self.ibmc)
-            conn.system.reset.assert_called_once_with(constants.RESET_NMI)
diff --git a/ironic/tests/unit/drivers/modules/ibmc/test_power.py b/ironic/tests/unit/drivers/modules/ibmc/test_power.py
deleted file mode 100644
index 58e6a738d6..0000000000
--- a/ironic/tests/unit/drivers/modules/ibmc/test_power.py
+++ /dev/null
@@ -1,288 +0,0 @@
-#
-# 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.
-"""Test class for iBMC Power interface."""
-
-from unittest import mock
-
-from oslo_utils import importutils
-
-from ironic.common import exception
-from ironic.common import states
-from ironic.conductor import task_manager
-from ironic.drivers.modules.ibmc import mappings
-from ironic.drivers.modules.ibmc import utils
-from ironic.tests.unit.drivers.modules.ibmc import base
-
-constants = importutils.try_import('ibmc_client.constants')
-ibmc_client = importutils.try_import('ibmc_client')
-ibmc_error = importutils.try_import('ibmc_client.exceptions')
-
-
-@mock.patch('oslo_utils.eventletutils.EventletEvent.wait',
-            lambda *args, **kwargs: None)
-class IBMCPowerTestCase(base.IBMCTestCase):
-
-    def test_get_properties(self):
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            properties = task.driver.get_properties()
-            for prop in utils.COMMON_PROPERTIES:
-                self.assertIn(prop, properties)
-
-    @mock.patch.object(utils, 'parse_driver_info', autospec=True)
-    def test_validate(self, mock_parse_driver_info):
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            task.driver.power.validate(task)
-            mock_parse_driver_info.assert_called_once_with(task.node)
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_get_power_state(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            expected_values = mappings.GET_POWER_STATE_MAP
-            for current, expected in expected_values.items():
-                # Mock
-                conn.system.get.return_value = mock.Mock(
-                    power_state=current
-                )
-
-                # Asserts
-                self.assertEqual(expected,
-                                 task.driver.power.get_power_state(task))
-
-                conn.system.get.assert_called_once()
-                connect_ibmc.assert_called_once_with(**self.ibmc)
-
-                # Reset Mock
-                conn.system.get.reset_mock()
-                connect_ibmc.reset_mock()
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_set_power_state(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            state_mapping = mappings.SET_POWER_STATE_MAP
-            for (expect_state, reset_type) in state_mapping.items():
-                if expect_state in (states.POWER_OFF, states.SOFT_POWER_OFF):
-                    final = constants.SYSTEM_POWER_STATE_OFF
-                    transient = constants.SYSTEM_POWER_STATE_ON
-                else:
-                    final = constants.SYSTEM_POWER_STATE_ON
-                    transient = constants.SYSTEM_POWER_STATE_OFF
-
-                # Mocks
-                mock_system_get_results = (
-                    [mock.Mock(power_state=transient)] * 3
-                    + [mock.Mock(power_state=final)])
-                conn.system.get.side_effect = mock_system_get_results
-
-                task.driver.power.set_power_state(task, expect_state)
-
-                # Asserts
-                connect_ibmc.assert_called_with(**self.ibmc)
-                conn.system.reset.assert_called_once_with(reset_type)
-                self.assertEqual(4, conn.system.get.call_count)
-
-                # Reset Mocks
-                # TODO(Qianbiao.NG) why reset_mock does not reset call_count
-                connect_ibmc.reset_mock()
-                conn.system.get.reset_mock()
-                conn.system.reset.reset_mock()
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_set_power_state_not_reached(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            self.config(power_state_change_timeout=2, group='conductor')
-
-            state_mapping = mappings.SET_POWER_STATE_MAP
-            for (expect_state, reset_type) in state_mapping.items():
-                if expect_state in (states.POWER_OFF, states.SOFT_POWER_OFF):
-                    final = constants.SYSTEM_POWER_STATE_OFF
-                    transient = constants.SYSTEM_POWER_STATE_ON
-                else:
-                    final = constants.SYSTEM_POWER_STATE_ON
-                    transient = constants.SYSTEM_POWER_STATE_OFF
-
-                # Mocks
-                mock_system_get_results = (
-                    [mock.Mock(power_state=transient)] * 5
-                    + [mock.Mock(power_state=final)])
-                conn.system.get.side_effect = mock_system_get_results
-
-                self.assertRaises(exception.PowerStateFailure,
-                                  task.driver.power.set_power_state,
-                                  task, expect_state)
-
-                # Asserts
-                connect_ibmc.assert_called_with(**self.ibmc)
-                conn.system.reset.assert_called_once_with(reset_type)
-
-                # Reset Mocks
-                connect_ibmc.reset_mock()
-                conn.system.get.reset_mock()
-                conn.system.reset.reset_mock()
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_set_power_state_fail(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-
-        # Mocks
-        conn.system.reset.side_effect = (
-            ibmc_error.IBMCClientError
-        )
-
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            # Asserts
-            self.assertRaisesRegex(
-                exception.IBMCError, 'set iBMC power state',
-                task.driver.power.set_power_state, task, states.POWER_ON)
-            connect_ibmc.assert_called_with(**self.ibmc)
-            conn.system.reset.assert_called_once_with(constants.RESET_ON)
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_set_power_state_timeout(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            self.config(power_state_change_timeout=2, group='conductor')
-
-            # Mocks
-            conn.system.get.side_effect = (
-                [mock.Mock(power_state=constants.SYSTEM_POWER_STATE_OFF)] * 3
-            )
-
-            # Asserts
-            self.assertRaisesRegex(
-                exception.PowerStateFailure,
-                'Failed to set node power state to power on',
-                task.driver.power.set_power_state, task, states.POWER_ON)
-
-            connect_ibmc.assert_called_with(**self.ibmc)
-            conn.system.reset.assert_called_once_with(constants.RESET_ON)
-
-    def test_get_supported_power_states(self):
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            supported_power_states = (
-                task.driver.power.get_supported_power_states(task))
-            self.assertEqual(sorted(list(mappings.SET_POWER_STATE_MAP)),
-                             sorted(supported_power_states))
-
-
-@mock.patch('oslo_utils.eventletutils.EventletEvent.wait',
-            lambda *args, **kwargs: None)
-class IBMCPowerRebootTestCase(base.IBMCTestCase):
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_reboot(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        expected_values = [
-            (constants.SYSTEM_POWER_STATE_OFF, constants.RESET_ON),
-            (constants.SYSTEM_POWER_STATE_ON,
-             constants.RESET_FORCE_RESTART)
-        ]
-
-        # for (expect_state, reset_type) in state_mapping.items():
-        for current, reset_type in expected_values:
-            mock_system_get_results = [
-                # Initial state
-                mock.Mock(power_state=current),
-                # Transient state - powering off
-                mock.Mock(power_state=constants.SYSTEM_POWER_STATE_OFF),
-                # Final state - down powering off
-                mock.Mock(power_state=constants.SYSTEM_POWER_STATE_ON)
-            ]
-            conn.system.get.side_effect = mock_system_get_results
-            with task_manager.acquire(self.context, self.node.uuid,
-                                      shared=False) as task:
-                task.driver.power.reboot(task)
-
-            # Asserts
-            connect_ibmc.assert_called_with(**self.ibmc)
-            conn.system.reset.assert_called_once_with(reset_type)
-
-            # Reset Mocks
-            connect_ibmc.reset_mock()
-            conn.system.get.reset_mock()
-            conn.system.reset.reset_mock()
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_reboot_not_reached(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-
-            # Mocks
-            conn.system.get.return_value = mock.Mock(
-                power_state=constants.SYSTEM_POWER_STATE_OFF)
-            self.assertRaisesRegex(
-                exception.PowerStateFailure,
-                'Failed to set node power state to power on',
-                task.driver.power.reboot, task)
-
-            # Asserts
-            connect_ibmc.assert_called_with(**self.ibmc)
-            conn.system.reset.assert_called_once_with(constants.RESET_ON)
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_reboot_fail(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-
-        # Mocks
-        conn.system.reset.side_effect = (
-            ibmc_error.IBMCClientError
-        )
-        conn.system.get.return_value = mock.Mock(
-            power_state=constants.SYSTEM_POWER_STATE_ON
-        )
-
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            # Asserts
-            self.assertRaisesRegex(
-                exception.IBMCError, 'reboot iBMC',
-                task.driver.power.reboot, task)
-            connect_ibmc.assert_called_with(**self.ibmc)
-            conn.system.get.assert_called_once()
-            conn.system.reset.assert_called_once_with(
-                constants.RESET_FORCE_RESTART)
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_reboot_timeout(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-
-        # Mocks
-        conn.system.get.side_effect = [mock.Mock(
-            power_state=constants.SYSTEM_POWER_STATE_OFF
-        )] * 5
-
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=False) as task:
-            self.config(power_state_change_timeout=2, group='conductor')
-
-            # Asserts
-            self.assertRaisesRegex(
-                exception.PowerStateFailure,
-                'Failed to set node power state to power on',
-                task.driver.power.reboot, task)
-
-            # Asserts
-            connect_ibmc.assert_called_with(**self.ibmc)
-            conn.system.reset.assert_called_once_with(
-                constants.RESET_ON)
diff --git a/ironic/tests/unit/drivers/modules/ibmc/test_raid.py b/ironic/tests/unit/drivers/modules/ibmc/test_raid.py
deleted file mode 100644
index 5b62a54e2e..0000000000
--- a/ironic/tests/unit/drivers/modules/ibmc/test_raid.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# 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.
-
-"""Test class for iBMC RAID interface."""
-
-from unittest import mock
-
-from oslo_utils import importutils
-
-from ironic.common import exception
-from ironic.conductor import task_manager
-from ironic.drivers.modules.ilo import raid as ilo_raid
-from ironic.tests.unit.db import utils as db_utils
-from ironic.tests.unit.drivers.modules.ibmc import base
-
-constants = importutils.try_import('ibmc_client.constants')
-ibmc_client = importutils.try_import('ibmc_client')
-ibmc_error = importutils.try_import('ibmc_client.exceptions')
-
-INFO_DICT = db_utils.get_test_ilo_info()
-
-
-class IbmcRAIDTestCase(base.IBMCTestCase):
-
-    def setUp(self):
-        super(IbmcRAIDTestCase, self).setUp()
-        self.driver = mock.Mock(raid=ilo_raid.Ilo5RAID())
-        self.target_raid_config = {
-            "logical_disks": [
-                {
-                    'size_gb': 200,
-                    'raid_level': 0,
-                    'is_root_volume': True
-                },
-                {
-                    'size_gb': 'MAX',
-                    'raid_level': 5
-                }
-            ]
-        }
-        self.node.target_raid_config = self.target_raid_config
-        self.node.save()
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_sync_create_configuration_without_delete(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        conn.system.storage.apply_raid_configuration.return_value = None
-
-        with task_manager.acquire(self.context, self.node.uuid) as task:
-            result = task.driver.raid.create_configuration(
-                task, create_root_volume=True, create_nonroot_volumes=True,
-                delete_existing=False)
-            self.assertIsNone(result, "synchronous create raid configuration "
-                                      "should return None")
-
-        conn.system.storage.apply_raid_configuration.assert_called_once_with(
-            self.node.target_raid_config.get('logical_disks')
-        )
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_sync_create_configuration_with_delete(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        conn.system.storage.delete_all_raid_configuration.return_value = None
-        conn.system.storage.apply_raid_configuration.return_value = None
-
-        with task_manager.acquire(self.context, self.node.uuid) as task:
-            result = task.driver.raid.create_configuration(
-                task, create_root_volume=True, create_nonroot_volumes=True,
-                delete_existing=True)
-            self.assertIsNone(result, "synchronous create raid configuration "
-                                      "should return None")
-
-        conn.system.storage.delete_all_raid_configuration.assert_called_once()
-        conn.system.storage.apply_raid_configuration.assert_called_once_with(
-            self.node.target_raid_config.get('logical_disks')
-        )
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_sync_create_configuration_without_nonroot(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        conn.system.storage.delete_all_raid_configuration.return_value = None
-        conn.system.storage.apply_raid_configuration.return_value = None
-
-        with task_manager.acquire(self.context, self.node.uuid) as task:
-            result = task.driver.raid.create_configuration(
-                task, create_root_volume=True, create_nonroot_volumes=False,
-                delete_existing=True)
-            self.assertIsNone(result, "synchronous create raid configuration "
-                                      "should return None")
-
-        conn.system.storage.delete_all_raid_configuration.assert_called_once()
-        conn.system.storage.apply_raid_configuration.assert_called_once_with(
-            [{'size_gb': 200, 'raid_level': 0, 'is_root_volume': True}]
-        )
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_sync_create_configuration_without_root(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        conn.system.storage.delete_all_raid_configuration.return_value = None
-        conn.system.storage.apply_raid_configuration.return_value = None
-
-        with task_manager.acquire(self.context, self.node.uuid) as task:
-            result = task.driver.raid.create_configuration(
-                task, create_root_volume=False, create_nonroot_volumes=True,
-                delete_existing=True)
-            self.assertIsNone(result, "synchronous create raid configuration "
-                                      "should return None")
-
-        conn.system.storage.delete_all_raid_configuration.assert_called_once()
-        conn.system.storage.apply_raid_configuration.assert_called_once_with(
-            [{'size_gb': 'MAX', 'raid_level': 5}]
-        )
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_sync_create_configuration_failed(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        conn.system.storage.delete_all_raid_configuration.return_value = None
-        conn.system.storage.apply_raid_configuration.side_effect = (
-            ibmc_error.IBMCClientError
-        )
-
-        with task_manager.acquire(self.context, self.node.uuid) as task:
-            self.assertRaisesRegex(
-                exception.IBMCError, 'create iBMC RAID configuration',
-                task.driver.raid.create_configuration, task,
-                create_root_volume=True, create_nonroot_volumes=True,
-                delete_existing=True)
-
-        conn.system.storage.delete_all_raid_configuration.assert_called_once()
-        conn.system.storage.apply_raid_configuration.assert_called_once_with(
-            self.node.target_raid_config.get('logical_disks')
-        )
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_sync_delete_configuration_success(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        conn.system.storage.delete_all_raid_configuration.return_value = None
-
-        with task_manager.acquire(self.context, self.node.uuid) as task:
-            result = task.driver.raid.delete_configuration(task)
-            self.assertIsNone(result, "synchronous delete raid configuration "
-                                      "should return None")
-
-        conn.system.storage.delete_all_raid_configuration.assert_called_once()
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_sync_delete_configuration_failed(self, connect_ibmc):
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        conn.system.storage.delete_all_raid_configuration.side_effect = (
-            ibmc_error.IBMCClientError
-        )
-
-        with task_manager.acquire(self.context, self.node.uuid) as task:
-            self.assertRaisesRegex(
-                exception.IBMCError, 'delete iBMC RAID configuration',
-                task.driver.raid.delete_configuration, task)
-
-        conn.system.storage.delete_all_raid_configuration.assert_called_once()
diff --git a/ironic/tests/unit/drivers/modules/ibmc/test_utils.py b/ironic/tests/unit/drivers/modules/ibmc/test_utils.py
deleted file mode 100644
index 6b5a44c231..0000000000
--- a/ironic/tests/unit/drivers/modules/ibmc/test_utils.py
+++ /dev/null
@@ -1,173 +0,0 @@
-#
-# 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.
-"""Test class for iBMC Driver common utils."""
-
-import copy
-import os
-from unittest import mock
-
-from oslo_utils import importutils
-
-from ironic.common import exception
-from ironic.conductor import task_manager
-from ironic.drivers.modules.ibmc import utils
-from ironic.tests.unit.drivers.modules.ibmc import base
-
-constants = importutils.try_import('ibmc_client.constants')
-ibmc_client = importutils.try_import('ibmc_client')
-ibmc_error = importutils.try_import('ibmc_client.exceptions')
-
-
-class IBMCUtilsTestCase(base.IBMCTestCase):
-
-    def setUp(self):
-        super(IBMCUtilsTestCase, self).setUp()
-        # Redfish specific configurations
-        self.config(connection_attempts=2, group='ibmc')
-        self.parsed_driver_info = {
-            'address': 'https://example.com',
-            'username': 'username',
-            'password': 'password',
-            'verify_ca': True,
-        }
-
-    def test_parse_driver_info(self):
-        response = utils.parse_driver_info(self.node)
-        self.assertEqual(self.parsed_driver_info, response)
-
-    def test_parse_driver_info_default_scheme(self):
-        self.node.driver_info['ibmc_address'] = 'example.com'
-        response = utils.parse_driver_info(self.node)
-        self.assertEqual(self.parsed_driver_info, response)
-
-    def test_parse_driver_info_default_scheme_with_port(self):
-        self.node.driver_info['ibmc_address'] = 'example.com:42'
-        self.parsed_driver_info['address'] = 'https://example.com:42'
-        response = utils.parse_driver_info(self.node)
-        self.assertEqual(self.parsed_driver_info, response)
-
-    def test_parse_driver_info_missing_info(self):
-        for prop in utils.REQUIRED_PROPERTIES:
-            self.node.driver_info = self.driver_info.copy()
-            self.node.driver_info.pop(prop)
-            self.assertRaises(exception.MissingParameterValue,
-                              utils.parse_driver_info, self.node)
-
-    def test_parse_driver_info_invalid_address(self):
-        for value in ['/banana!', '#location', '?search=hello']:
-            self.node.driver_info['ibmc_address'] = value
-            self.assertRaisesRegex(exception.InvalidParameterValue,
-                                   'Invalid iBMC address',
-                                   utils.parse_driver_info, self.node)
-
-    @mock.patch.object(os.path, 'exists', autospec=True)
-    def test_parse_driver_info_path_verify_ca(self,
-                                              mock_isdir):
-        mock_isdir.return_value = True
-        fake_path = '/path/to/a/valid/CA'
-        self.node.driver_info['ibmc_verify_ca'] = fake_path
-        self.parsed_driver_info['verify_ca'] = fake_path
-
-        response = utils.parse_driver_info(self.node)
-        self.assertEqual(self.parsed_driver_info, response)
-        mock_isdir.assert_called_once_with(fake_path)
-
-    @mock.patch.object(os.path, 'exists', autospec=True)
-    def test_parse_driver_info_valid_capath(self, mock_isfile):
-        mock_isfile.return_value = True
-        fake_path = '/path/to/a/valid/CA.pem'
-        self.node.driver_info['ibmc_verify_ca'] = fake_path
-        self.parsed_driver_info['verify_ca'] = fake_path
-
-        response = utils.parse_driver_info(self.node)
-        self.assertEqual(self.parsed_driver_info, response)
-        mock_isfile.assert_called_once_with(fake_path)
-
-    def test_parse_driver_info_invalid_value_verify_ca(self):
-        # Integers are not supported
-        self.node.driver_info['ibmc_verify_ca'] = 123456
-        self.assertRaisesRegex(exception.InvalidParameterValue,
-                               'Invalid value type',
-                               utils.parse_driver_info, self.node)
-
-    def test_parse_driver_info_valid_string_value_verify_ca(self):
-        for value in ('0', 'f', 'false', 'off', 'n', 'no'):
-            self.node.driver_info['ibmc_verify_ca'] = value
-            response = utils.parse_driver_info(self.node)
-            parsed_driver_info = copy.deepcopy(self.parsed_driver_info)
-            parsed_driver_info['verify_ca'] = False
-            self.assertEqual(parsed_driver_info, response)
-
-        for value in ('1', 't', 'true', 'on', 'y', 'yes'):
-            self.node.driver_info['ibmc_verify_ca'] = value
-            response = utils.parse_driver_info(self.node)
-            self.assertEqual(self.parsed_driver_info, response)
-
-    def test_parse_driver_info_invalid_string_value_verify_ca(self):
-        for value in ('xyz', '*', '!123', '123'):
-            self.node.driver_info['ibmc_verify_ca'] = value
-            self.assertRaisesRegex(exception.InvalidParameterValue,
-                                   'The value should be a Boolean',
-                                   utils.parse_driver_info, self.node)
-
-    def test_revert_dictionary(self):
-        data = {
-            "key1": "value1",
-            "key2": "value2"
-        }
-
-        revert = utils.revert_dictionary(data)
-        self.assertEqual({
-            "value1": "key1",
-            "value2": "key2"
-        }, revert)
-
-    @mock.patch('time.sleep', autospec=True)
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_handle_ibmc_exception_retry(self, connect_ibmc, mock_sleep):
-
-        @utils.handle_ibmc_exception('get IBMC system')
-        def get_ibmc_system(_task):
-            driver_info = utils.parse_driver_info(_task.node)
-            with ibmc_client.connect(**driver_info) as _conn:
-                return _conn.system.get()
-
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        # Mocks
-        conn.system.get.side_effect = [
-            ibmc_error.IBMCConnectionError(url=self.ibmc['address'],
-                                           error='Failed to connect to host'),
-            mock.PropertyMock(
-                boot_source_override=mock.PropertyMock(
-                    target=constants.BOOT_SOURCE_TARGET_PXE,
-                    enabled=constants.BOOT_SOURCE_ENABLED_CONTINUOUS
-                )
-            )
-        ]
-
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            system = get_ibmc_system(task)
-
-            # Asserts
-            self.assertEqual(constants.BOOT_SOURCE_TARGET_PXE,
-                             system.boot_source_override.target)
-            self.assertEqual(constants.BOOT_SOURCE_ENABLED_CONTINUOUS,
-                             system.boot_source_override.enabled)
-
-            # 1 failed, 1 succeed
-            connect_ibmc.assert_called_with(**self.ibmc)
-            self.assertEqual(2, connect_ibmc.call_count)
-
-            # 1 failed, 1 succeed
-            self.assertEqual(2, conn.system.get.call_count)
diff --git a/ironic/tests/unit/drivers/modules/ibmc/test_vendor.py b/ironic/tests/unit/drivers/modules/ibmc/test_vendor.py
deleted file mode 100644
index 85fd39121b..0000000000
--- a/ironic/tests/unit/drivers/modules/ibmc/test_vendor.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# 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.
-"""Test class for iBMC vendor interface."""
-
-from unittest import mock
-
-from oslo_utils import importutils
-
-from ironic.conductor import task_manager
-from ironic.drivers.modules.ibmc import utils
-from ironic.tests.unit.drivers.modules.ibmc import base
-
-ibmc_client = importutils.try_import('ibmc_client')
-
-
-@mock.patch('oslo_utils.eventletutils.EventletEvent.wait',
-            lambda *args, **kwargs: None)
-class IBMCVendorTestCase(base.IBMCTestCase):
-
-    def setUp(self):
-        super(IBMCVendorTestCase, self).setUp()
-
-    def test_get_properties(self):
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            properties = task.driver.get_properties()
-            for prop in utils.COMMON_PROPERTIES:
-                self.assertIn(prop, properties)
-
-    @mock.patch.object(utils, 'parse_driver_info', autospec=True)
-    def test_validate(self, mock_parse_driver_info):
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            task.driver.power.validate(task)
-            mock_parse_driver_info.assert_called_once_with(task.node)
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_list_boot_type_order(self, connect_ibmc):
-        # Mocks
-        conn = self.mock_ibmc_conn(connect_ibmc)
-        boot_up_seq = ['Pxe', 'Hdd', 'Others', 'Cd']
-        conn.system.get.return_value = mock.Mock(
-            boot_sequence=['Pxe', 'Hdd', 'Others', 'Cd']
-        )
-
-        expected = {'boot_up_sequence': boot_up_seq}
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            seq = task.driver.vendor.boot_up_seq(task)
-            conn.system.get.assert_called_once_with()
-            connect_ibmc.assert_called_once_with(**self.ibmc)
-            self.assertEqual(expected, seq)
-
-    @mock.patch.object(ibmc_client, 'connect', spec=object)
-    def test_list_raid_controller(self, connect_ibmc):
-        # Mocks
-        conn = self.mock_ibmc_conn(connect_ibmc)
-
-        ctrl = mock.Mock()
-        summary = ctrl.summary.return_value
-        conn.system.storage.list.return_value = [ctrl]
-
-        with task_manager.acquire(self.context, self.node.uuid,
-                                  shared=True) as task:
-            summries = task.driver.vendor.get_raid_controller_list(task)
-            ctrl.summary.assert_called_once_with()
-            conn.system.storage.list.assert_called_once_with()
-            connect_ibmc.assert_called_once_with(**self.ibmc)
-            self.assertEqual([summary], summries)
diff --git a/ironic/tests/unit/drivers/modules/intel_ipmi/base.py b/ironic/tests/unit/drivers/modules/intel_ipmi/base.py
index 0e9fbe0161..39375ec418 100644
--- a/ironic/tests/unit/drivers/modules/intel_ipmi/base.py
+++ b/ironic/tests/unit/drivers/modules/intel_ipmi/base.py
@@ -10,7 +10,7 @@
 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 # License for the specific language governing permissions and limitations
 # under the License.
-"""Test base class for iBMC Driver."""
+"""Test base class for intel ipmi Driver."""
 
 from ironic.tests.unit.db import base as db_base
 from ironic.tests.unit.db import utils as db_utils
diff --git a/ironic/tests/unit/drivers/test_ibmc.py b/ironic/tests/unit/drivers/test_ibmc.py
deleted file mode 100644
index 019b50be6f..0000000000
--- a/ironic/tests/unit/drivers/test_ibmc.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# 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.
-
-# Version 1.0.0
-
-from ironic.conductor import task_manager
-from ironic.drivers.modules import agent
-from ironic.drivers.modules.ibmc import management as ibmc_mgmt
-from ironic.drivers.modules.ibmc import power as ibmc_power
-from ironic.drivers.modules.ibmc import raid as ibmc_raid
-from ironic.drivers.modules.ibmc import vendor as ibmc_vendor
-from ironic.drivers.modules import inspector
-from ironic.drivers.modules import noop
-from ironic.drivers.modules import pxe
-from ironic.tests.unit.db import base as db_base
-from ironic.tests.unit.objects import utils as obj_utils
-
-
-class IBMCHardwareTestCase(db_base.DbTestCase):
-
-    def setUp(self):
-        super(IBMCHardwareTestCase, self).setUp()
-        self.config(enabled_hardware_types=['ibmc'],
-                    enabled_power_interfaces=['ibmc'],
-                    enabled_management_interfaces=['ibmc'],
-                    enabled_vendor_interfaces=['ibmc'],
-                    enabled_raid_interfaces=['ibmc'],
-                    enabled_inspect_interfaces=['inspector', 'no-inspect'])
-
-    def test_default_interfaces(self):
-        node = obj_utils.create_test_node(self.context, driver='ibmc')
-        with task_manager.acquire(self.context, node.id) as task:
-            self.assertIsInstance(task.driver.management,
-                                  ibmc_mgmt.IBMCManagement)
-            self.assertIsInstance(task.driver.power,
-                                  ibmc_power.IBMCPower)
-            self.assertIsInstance(task.driver.boot, pxe.PXEBoot)
-            self.assertIsInstance(task.driver.console, noop.NoConsole)
-            self.assertIsInstance(task.driver.deploy, agent.AgentDeploy)
-            self.assertIsInstance(task.driver.raid, ibmc_raid.IbmcRAID)
-            self.assertIsInstance(task.driver.vendor, ibmc_vendor.IBMCVendor)
-            self.assertIsInstance(task.driver.inspect, inspector.Inspector)
diff --git a/ironic/tests/unit/drivers/third_party_driver_mock_specs.py b/ironic/tests/unit/drivers/third_party_driver_mock_specs.py
index 8dedc2fe10..e6c429b95c 100644
--- a/ironic/tests/unit/drivers/third_party_driver_mock_specs.py
+++ b/ironic/tests/unit/drivers/third_party_driver_mock_specs.py
@@ -121,10 +121,3 @@ SCCICLIENT_VIOM_CONF_SPEC = (
 REDFISH_SPEC = (
     'redfish',
 )
-
-# python-ibmcclient
-IBMCCLIENT_SPEC = (
-    'connect',
-    'exceptions',
-    'constants',
-)
diff --git a/ironic/tests/unit/drivers/third_party_driver_mocks.py b/ironic/tests/unit/drivers/third_party_driver_mocks.py
index 1d05f08e90..ddaf240160 100644
--- a/ironic/tests/unit/drivers/third_party_driver_mocks.py
+++ b/ironic/tests/unit/drivers/third_party_driver_mocks.py
@@ -27,7 +27,6 @@ Current list of mocked libraries:
 - pysnmp
 - scciclient
 - python-dracclient
-- python-ibmcclient
 - sushy_oem_idrac
 """
 
@@ -194,44 +193,3 @@ class MockKwargsException(Exception):
     def __init__(self, *args, **kwargs):
         super(MockKwargsException, self).__init__(*args)
         self.kwargs = kwargs
-
-
-# python-ibmcclient mocks for HUAWEI rack server driver
-ibmc_client = importutils.try_import('ibmc_client')
-if not ibmc_client:
-    ibmc_client = mock.MagicMock(spec_set=mock_specs.IBMCCLIENT_SPEC)
-    sys.modules['ibmc_client'] = ibmc_client
-
-    # Mock iBMC client exceptions
-    exceptions = mock.MagicMock()
-    exceptions.IBMCConnectionError = (
-        type('IBMCConnectionError', (MockKwargsException,), {}))
-    exceptions.IBMCClientError = (
-        type('IBMCClientError', (MockKwargsException,), {}))
-    sys.modules['ibmc_client.exceptions'] = exceptions
-
-    # Mock iIBMC client constants
-    constants = mock.MagicMock(
-        SYSTEM_POWER_STATE_ON='On',
-        SYSTEM_POWER_STATE_OFF='Off',
-        BOOT_SOURCE_TARGET_NONE='None',
-        BOOT_SOURCE_TARGET_PXE='Pxe',
-        BOOT_SOURCE_TARGET_FLOPPY='Floppy',
-        BOOT_SOURCE_TARGET_CD='Cd',
-        BOOT_SOURCE_TARGET_HDD='Hdd',
-        BOOT_SOURCE_TARGET_BIOS_SETUP='BiosSetup',
-        BOOT_SOURCE_MODE_BIOS='Legacy',
-        BOOT_SOURCE_MODE_UEFI='UEFI',
-        BOOT_SOURCE_ENABLED_ONCE='Once',
-        BOOT_SOURCE_ENABLED_CONTINUOUS='Continuous',
-        BOOT_SOURCE_ENABLED_DISABLED='Disabled',
-        RESET_NMI='Nmi',
-        RESET_ON='On',
-        RESET_FORCE_OFF='ForceOff',
-        RESET_GRACEFUL_SHUTDOWN='GracefulShutdown',
-        RESET_FORCE_RESTART='ForceRestart',
-        RESET_FORCE_POWER_CYCLE='ForcePowerCycle')
-    sys.modules['ibmc_client.constants'] = constants
-
-    if 'ironic.drivers.modules.ibmc' in sys.modules:
-        importlib.reload(sys.modules['ironic.drivers.modules.ibmc'])
diff --git a/releasenotes/notes/remove-deprecated-ibmc-driver-0c90817d8ad0ccc4.yaml b/releasenotes/notes/remove-deprecated-ibmc-driver-0c90817d8ad0ccc4.yaml
new file mode 100644
index 0000000000..6c9b690ece
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-ibmc-driver-0c90817d8ad0ccc4.yaml
@@ -0,0 +1,4 @@
+---
+upgrade:
+  - |
+    The deprecated ``ibmc`` hardware type has been removed from Ironic.
diff --git a/setup.cfg b/setup.cfg
index 90cb8fb213..a2369e7e8e 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -119,7 +119,6 @@ ironic.hardware.interfaces.inspect =
 
 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
@@ -139,7 +138,6 @@ ironic.hardware.interfaces.network =
 ironic.hardware.interfaces.power =
     agent = ironic.drivers.modules.agent_power:AgentPower
     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
@@ -152,7 +150,6 @@ ironic.hardware.interfaces.power =
 ironic.hardware.interfaces.raid =
     agent = ironic.drivers.modules.agent:AgentRAID
     fake = ironic.drivers.modules.fake:FakeRAID
-    ibmc = ironic.drivers.modules.ibmc.raid:IbmcRAID
     idrac = ironic.drivers.modules.drac.raid:DracRAID
     idrac-redfish = ironic.drivers.modules.drac.raid:DracRedfishRAID
     idrac-wsman = ironic.drivers.modules.drac.raid:DracWSManRAID
@@ -174,7 +171,6 @@ ironic.hardware.interfaces.storage =
 
 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
     idrac-redfish = ironic.drivers.modules.drac.vendor_passthru:DracRedfishVendorPassthru
@@ -186,7 +182,6 @@ ironic.hardware.interfaces.vendor =
 
 ironic.hardware.types =
     fake-hardware = ironic.drivers.fake_hardware:FakeHardware
-    ibmc = ironic.drivers.ibmc:IBMCHardware
     idrac = ironic.drivers.drac:IDRACHardware
     ilo = ironic.drivers.ilo:IloHardware
     ilo5 = ironic.drivers.ilo:Ilo5Hardware