From 1a07137118a95d72b3eb3b66121ee337fb989429 Mon Sep 17 00:00:00 2001
From: Dmitry Tantsur <divius.inside@gmail.com>
Date: Tue, 26 Jun 2018 14:51:35 +0200
Subject: [PATCH] Remove the ipmitool classic drivers

This change removes pxe_ipmitool and agent_ipmitool. Some tests
and documentation bits are removed, since we no longer have any
classic drivers to provide examples.

The Inspector.create_if_enabled method is no longer used and was
removed. The [inspector]enabled option will be deprecated in
a follow-up.

IRONIC_ENABLED_DRIVERS is removed from devstack to prevent
devstack-gate from injecting the removed drivers into it.
A temporary migration from queens is updated to disable all
classic drivers. It will be removed when the enabled_drivers
option is completely removed.

Change-Id: Iab247e3b3336f90446ef0687edb340cf8282a925
---
 devstack/lib/ironic                           |  32 ++---
 devstack/upgrade/from-queens/upgrade-ironic   |   6 +-
 doc/source/admin/drivers/ipmitool.rst         |  35 ++---
 doc/source/admin/inspection.rst               |   8 --
 doc/source/admin/report.txt                   |   4 -
 doc/source/install/enabling-drivers.rst       |  31 +---
 doc/source/install/enrollment.rst             |   1 -
 ironic/conf/default.py                        |   2 +-
 ironic/db/api.py                              |   2 +-
 ironic/drivers/agent.py                       |  20 ---
 ironic/drivers/ipmi.py                        | 133 ------------------
 ironic/drivers/modules/inspector.py           |  15 --
 .../tests/unit/common/test_driver_factory.py  |   7 -
 .../unit/drivers/modules/test_inspector.py    |  41 ------
 ironic/tests/unit/drivers/test_ipmi.py        |  52 -------
 .../run.yaml                                  |   6 +-
 .../no-classic-ipmi-7ec52a7b01e40536.yaml     |   5 +
 setup.cfg                                     |   6 -
 18 files changed, 38 insertions(+), 368 deletions(-)
 delete mode 100644 ironic/drivers/agent.py
 create mode 100644 releasenotes/notes/no-classic-ipmi-7ec52a7b01e40536.yaml

diff --git a/devstack/lib/ironic b/devstack/lib/ironic
index e37666282a..f58f34b504 100644
--- a/devstack/lib/ironic
+++ b/devstack/lib/ironic
@@ -101,7 +101,7 @@ IRONIC_HW_ARCH=${IRONIC_HW_ARCH:-x86_64}
 # 192.168.110.107 00:1e:67:57:50:4c root otc123
 #
 # Supported IRONIC_DEPLOY_DRIVERs:
-# *_ipmitool or ipmi:
+# ipmi:
 #   <BMC address> <MAC address> <BMC username> <BMC password>
 #
 # cisco-ucs-standalone:
@@ -156,13 +156,6 @@ if [[ -n "$IRONIC_DEFAULT_API_VERSION" ]]; then
     IRONIC_CMD="$IRONIC_CMD --os-baremetal-api-version $IRONIC_DEFAULT_API_VERSION"
 fi
 
-# driver / hardware type options
-IRONIC_ENABLED_DRIVERS=${IRONIC_ENABLED_DRIVERS:-pxe_ipmitool,agent_ipmitool}
-# NOTE(dtantsur): some places (I'm looking at you, devstack-gate) still
-# hardcode "fake", and we cannot fix them without breaking stable branches.
-# This ugly hack is only needed until we delete IRONIC_ENABLED_DRIVERS
-# in the near future.
-IRONIC_ENABLED_DRIVERS=$(echo $IRONIC_ENABLED_DRIVERS | sed -r 's/fake,?//')
 IRONIC_ENABLED_HARDWARE_TYPES=${IRONIC_ENABLED_HARDWARE_TYPES:-"ipmi,fake-hardware"}
 # list of all available driver interfaces types
 IRONIC_DRIVER_INTERFACE_TYPES="bios boot power management deploy console inspect raid rescue storage network vendor"
@@ -289,16 +282,16 @@ if [[ "$IRONIC_DEPLOY_ISO_REQUIRED" = "True" \
         or set IRONIC_BUILD_DEPLOY_RAMDISK=True to use ISOs"
 fi
 # Which deploy driver to use - valid choices right now
-# are ``pxe_ipmitool``, ``agent_ipmitool``, ``snmp`` and ``ipmi``.
+# are ``ipmi``, ``snmp`` and ``redfish``.
 #
 # Additional valid choices if IRONIC_IS_HARDWARE == true are:
 # ``cisco-ucs-managed``, ``cisco-ucs-standalone``, ``oneview`` and ``idrac``.
-IRONIC_DEPLOY_DRIVER=${IRONIC_DEPLOY_DRIVER:-pxe_ipmitool}
+IRONIC_DEPLOY_DRIVER=${IRONIC_DEPLOY_DRIVER:-ipmi}
 
 # If the requested driver is not yet enable, enable it, if it is not it will fail anyway
-if [[ -z "$(echo ${IRONIC_ENABLED_DRIVERS},${IRONIC_ENABLED_HARDWARE_TYPES} | grep -w ${IRONIC_DEPLOY_DRIVER})" ]]; then
+if [[ -z "$(echo ${IRONIC_ENABLED_HARDWARE_TYPES} | grep -w ${IRONIC_DEPLOY_DRIVER})" ]]; then
     die "The deploy driver $IRONIC_DEPLOY_DRIVER is not in the list of enabled \
-        drivers $IRONIC_ENABLED_DRIVERS or hardware types $IRONIC_ENABLED_HARDWARE_TYPES"
+        hardware types $IRONIC_ENABLED_HARDWARE_TYPES"
 fi
 
 # Support entry points installation of console scripts
@@ -613,8 +606,8 @@ function is_deployed_by_agent {
     return 1
 }
 
-function is_deployed_by_ipmitool {
-    [[ "$IRONIC_DEPLOY_DRIVER" == ipmi || -z "${IRONIC_DEPLOY_DRIVER##*_ipmitool}" ]] && return 0
+function is_deployed_by_ipmi {
+    [[ "$IRONIC_DEPLOY_DRIVER" == ipmi ]] && return 0
     return 1
 }
 
@@ -873,7 +866,7 @@ function install_ironic {
         restart_libvirt
     fi
 
-    if is_deployed_by_ipmitool && [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
+    if is_deployed_by_ipmi && [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
         setup_virtualbmc
     fi
 
@@ -1221,7 +1214,6 @@ function configure_ironic_conductor {
     configure_rootwrap ironic
 
     # set up drivers / hardware types
-    iniset $IRONIC_CONF_FILE DEFAULT enabled_drivers $IRONIC_ENABLED_DRIVERS
     iniset $IRONIC_CONF_FILE DEFAULT enabled_hardware_types $IRONIC_ENABLED_HARDWARE_TYPES
 
     # configure enabled and default interfaces
@@ -1820,7 +1812,7 @@ function enroll_nodes {
         local ironic_node_arch=x86_64
         local ironic_hwinfo_file=$IRONIC_VM_MACS_CSV_FILE
 
-        if is_deployed_by_ipmitool; then
+        if is_deployed_by_ipmi; then
             local node_options="\
                 --driver-info ipmi_address=${HOST_IP} \
                 --driver-info ipmi_username=admin \
@@ -1873,7 +1865,7 @@ function enroll_nodes {
         if [[ "$IRONIC_IS_HARDWARE" == "False" ]]; then
             interface_info=$(echo $hardware_info | awk '{print $1}')
 
-            if is_deployed_by_ipmitool; then
+            if is_deployed_by_ipmi; then
                 local vbmc_port
                 vbmc_port=$(echo $hardware_info | awk '{print $2}')
                 node_options+=" --driver-info ipmi_port=$vbmc_port"
@@ -1921,7 +1913,7 @@ function enroll_nodes {
             bmc_passwd=$(echo $hardware_info |awk '{print $4}')
             local node_options="$common_node_options"
 
-            if is_deployed_by_ipmitool; then
+            if is_deployed_by_ipmi; then
                 node_options+=" --driver-info ipmi_address=$bmc_address \
                     --driver-info ipmi_password=$bmc_passwd \
                     --driver-info ipmi_username=$bmc_username"
@@ -2515,7 +2507,7 @@ function ironic_configure_tempest {
         iniset $TEMPEST_CONFIG baremetal whole_disk_image_checksum $(md5sum $FILES/${IRONIC_WHOLEDISK_IMAGE_NAME}.img)
     fi
 
-    iniset $TEMPEST_CONFIG baremetal enabled_drivers $IRONIC_ENABLED_DRIVERS
+    iniset $TEMPEST_CONFIG baremetal enabled_drivers ""
     iniset $TEMPEST_CONFIG baremetal enabled_hardware_types $IRONIC_ENABLED_HARDWARE_TYPES
     iniset $TEMPEST_CONFIG baremetal enabled_bios_interfaces $IRONIC_ENABLED_BIOS_INTERFACES
     iniset $TEMPEST_CONFIG baremetal enabled_deploy_interfaces $IRONIC_ENABLED_DEPLOY_INTERFACES
diff --git a/devstack/upgrade/from-queens/upgrade-ironic b/devstack/upgrade/from-queens/upgrade-ironic
index 15ca9a9974..fe66d8b381 100644
--- a/devstack/upgrade/from-queens/upgrade-ironic
+++ b/devstack/upgrade/from-queens/upgrade-ironic
@@ -1,5 +1,5 @@
 function configure_ironic_upgrade {
-    # Remove the fake driver from the configuration (forced by devstack-gate)
-    drivers=$(iniget $IRONIC_CONF_FILE DEFAULT enabled_drivers | sed -r 's/fake,?//')
-    iniset $IRONIC_CONF_FILE DEFAULT enabled_drivers $drivers
+    # Remove the classic drivers from the configuration (forced by devstack-gate)
+    # TODO(dtantsur): remove when classic drivers are removed
+    sed -i '/^enabled_drivers/d' $IRONIC_CONF_FILE
 }
diff --git a/doc/source/admin/drivers/ipmitool.rst b/doc/source/admin/drivers/ipmitool.rst
index 60fee146b5..160f742f99 100644
--- a/doc/source/admin/drivers/ipmitool.rst
+++ b/doc/source/admin/drivers/ipmitool.rst
@@ -1,29 +1,15 @@
-===============
-IPMITool driver
-===============
+===========
+IPMI driver
+===========
 
 Overview
 ========
 
-The IPMI_ (Intelligent Platform Management Interface) drivers manage nodes
-by using IPMI protocol versions 2.0 or 1.5. They use the IPMItool_ utility
-which is an open-source command-line interface (CLI) for controlling
+The ``ipmi``  hardware type manage nodes by using IPMI_ (Intelligent Platform
+Management Interface) protocol versions 2.0 or 1.5. It uses the IPMItool_
+utility which is an open-source command-line interface (CLI) for controlling
 IPMI-enabled devices.
 
-The following hardware types and classic drivers use IPMItool for power and
-management:
-
-* hardware types:
-
-  * ``ipmi``
-
-* classic drivers:
-
-  * ``agent_ipmitool``
-  * ``pxe_ipmitool``
-  * ``agent_ipmitool_socat``
-  * ``pxe_ipmitool_socat``
-
 Glossary
 ========
 
@@ -32,7 +18,7 @@ Glossary
 * BMC_  - Baseboard Management Controller.
 * RMCP - Remote Management Control Protocol.
 
-Enabling the IPMItool driver(s)
+Enabling the IPMI hardware type
 ===============================
 
 Please see :doc:`/install/configure-ipmi` for the required dependencies.
@@ -49,12 +35,11 @@ Please see :doc:`/install/configure-ipmi` for the required dependencies.
 
 Please see :doc:`/install/enabling-drivers` for more details.
 
-Registering a node with the IPMItool driver
-===========================================
+Registering a node with the IPMI driver
+=======================================
 
 Nodes configured to use the IPMItool drivers should have the ``driver`` field
-set to ``ipmi`` (hardware type) or to the name of one of the classic drivers
-that support IPMItool.
+set to ``ipmi``.
 
 The following configuration value is required and has to be added to
 the node's ``driver_info`` field:
diff --git a/doc/source/admin/inspection.rst b/doc/source/admin/inspection.rst
index 51bf7fc199..3c03406ab8 100644
--- a/doc/source/admin/inspection.rst
+++ b/doc/source/admin/inspection.rst
@@ -86,14 +86,6 @@ enabled to use it:
     [DEFAULT]
     enabled_inspect_interfaces = inspector,no-inspect
 
-If using classic drivers supporting in-band inspection, like ``pxe_ipmitool``,
-another option has to be set as well:
-
-.. code-block:: ini
-
-    [inspector]
-    enabled = True
-
 You must additionally install python-ironic-inspector-client_ to use
 this functionality.
 
diff --git a/doc/source/admin/report.txt b/doc/source/admin/report.txt
index c63ad63737..583c5aef62 100644
--- a/doc/source/admin/report.txt
+++ b/doc/source/admin/report.txt
@@ -262,10 +262,6 @@ default:
   enabled_deploy_interfaces =
     direct
     iscsi
-  enabled_drivers =
-    agent_ipmitool
-    fake
-    pxe_ipmitool
   enabled_hardware_types =
     ipmi
     redfish
diff --git a/doc/source/install/enabling-drivers.rst b/doc/source/install/enabling-drivers.rst
index 9363ade15c..5703469f0d 100644
--- a/doc/source/install/enabling-drivers.rst
+++ b/doc/source/install/enabling-drivers.rst
@@ -6,9 +6,8 @@ Introduction
 
 The Bare Metal service delegates actual hardware management to **drivers**.
 Starting with the Ocata release, two types of drivers are supported:
-*classic drivers* (for example, ``pxe_ipmitool``, etc.) and
-the newer *hardware types* (for example, generic ``redfish`` and ``ipmi``
-or vendor-specific ``ilo`` and ``irmc``).
+*classic drivers*  and the newer *hardware types* (for example, generic
+``redfish`` and ``ipmi`` or vendor-specific ``ilo`` and ``irmc``).
 
 Drivers, in turn, consist of *hardware interfaces*: sets of functionality
 dealing with some aspect of bare metal provisioning in a vendor-specific way.
@@ -301,32 +300,6 @@ existing nodes.
    support the provided default implementation, its users will have to always
    provide an explicit value for this interface when creating a node.
 
-Enabling classic drivers
-------------------------
-
-Classic drivers are enabled in the configuration file of the
-**ironic-conductor** service by setting the ``enabled_drivers`` configuration
-option, for example:
-
-.. code-block:: ini
-
-    [DEFAULT]
-    enabled_drivers = pxe_ipmitool
-
-The names in this comma-separated list are entry point names of the drivers.
-They have to be available at conductor start-up, and all dependencies must
-be installed locally. For example,
-
-* drivers starting with ``pxe`` and some drivers starting with ``agent``
-  require :doc:`configure-pxe`,
-
-* drivers starting with ``pxe`` or having ``iscsi`` in their name require
-  :doc:`configure-iscsi`,
-
-* drivers ending with ``ipmitool`` require :doc:`configure-ipmi`.
-
-See :doc:`/admin/drivers` for the required configuration of each driver.
-
 .. _driver composition reform specification: https://specs.openstack.org/openstack/ironic-specs/specs/approved/driver-composition-reform.html
 .. _setup.cfg: https://git.openstack.org/cgit/openstack/ironic/tree/setup.cfg
 .. _ironic-inspector: https://docs.openstack.org/ironic-inspector/latest/
diff --git a/doc/source/install/enrollment.rst b/doc/source/install/enrollment.rst
index cb7a1e63eb..eaad71402a 100644
--- a/doc/source/install/enrollment.rst
+++ b/doc/source/install/enrollment.rst
@@ -42,7 +42,6 @@ to list all drivers enabled on all hosts:
     | Supported driver(s) | Active host(s)        |
     +---------------------+-----------------------+
     | ipmi                | localhost.localdomain |
-    | pxe_ipmitool        | localhost.localdomain |
     +---------------------+-----------------------+
 
 Starting with API version 1.31 (and ``python-ironicclient`` 1.13), you can
diff --git a/ironic/conf/default.py b/ironic/conf/default.py
index c53db8317f..7740187e8e 100644
--- a/ironic/conf/default.py
+++ b/ironic/conf/default.py
@@ -90,7 +90,7 @@ api_opts = [
 
 driver_opts = [
     cfg.ListOpt('enabled_drivers',
-                default=['pxe_ipmitool'],
+                default=[],
                 help=_('Specify the list of drivers to load during service '
                        'initialization. Missing drivers, or drivers which '
                        'fail to initialize, will prevent the conductor '
diff --git a/ironic/db/api.py b/ironic/db/api.py
index aa6bf84909..bac5b9ec3f 100644
--- a/ironic/db/api.py
+++ b/ironic/db/api.py
@@ -138,7 +138,7 @@ class Connection(object):
                          'instance_uuid': None,
                          'power_state': states.POWER_OFF,
                          'provision_state': states.AVAILABLE,
-                         'driver': 'pxe_ipmitool',
+                         'driver': 'ipmi',
                          'driver_info': { ... },
                          'properties': { ... },
                          'extra': { ... },
diff --git a/ironic/drivers/agent.py b/ironic/drivers/agent.py
deleted file mode 100644
index ddad1059c1..0000000000
--- a/ironic/drivers/agent.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2014 Rackspace, Inc.
-#
-# 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.
-
-from ironic.drivers import ipmi
-
-
-# For backward compatibility
-AgentAndIPMIToolDriver = ipmi.AgentAndIPMIToolDriver
-AgentAndIPMIToolAndSocatDriver = ipmi.AgentAndIPMIToolAndSocatDriver
diff --git a/ironic/drivers/ipmi.py b/ironic/drivers/ipmi.py
index 7bdbc341aa..8f41fba3ff 100644
--- a/ironic/drivers/ipmi.py
+++ b/ironic/drivers/ipmi.py
@@ -14,19 +14,9 @@
 Hardware types and classic drivers for IPMI (using ipmitool).
 """
 
-from oslo_config import cfg
-
-from ironic.drivers import base
 from ironic.drivers import generic
-from ironic.drivers.modules import agent
-from ironic.drivers.modules import inspector
 from ironic.drivers.modules import ipmitool
-from ironic.drivers.modules import iscsi_deploy
 from ironic.drivers.modules import noop
-from ironic.drivers.modules import pxe
-
-
-CONF = cfg.CONF
 
 
 class IPMIHardware(generic.GenericHardware):
@@ -56,126 +46,3 @@ class IPMIHardware(generic.GenericHardware):
     def supported_vendor_interfaces(self):
         """List of supported vendor interfaces."""
         return [ipmitool.VendorPassthru, noop.NoVendor]
-
-
-def _to_hardware_type():
-    # NOTE(dtantsur): classic drivers are not affected by the
-    # enabled_inspect_interfaces configuration option.
-    if CONF.inspector.enabled:
-        inspect_interface = 'inspector'
-    else:
-        inspect_interface = 'no-inspect'
-
-    return {'boot': 'pxe',
-            'inspect': inspect_interface,
-            'management': 'ipmitool',
-            'power': 'ipmitool',
-            'raid': 'agent',
-            'vendor': 'ipmitool'}
-
-
-class PXEAndIPMIToolDriver(base.BaseDriver):
-    """PXE + IPMITool driver.
-
-    This driver implements the `core` functionality, combining
-    :class:`ironic.drivers.modules.ipmitool.IPMIPower` for power on/off
-    and reboot with
-    :class:`ironic.drivers.modules.iscsi_deploy.ISCSIDeploy` for
-    image deployment. Implementations are in those respective
-    classes; this class is merely the glue between them.
-    """
-    def __init__(self):
-        self.power = ipmitool.IPMIPower()
-        self.console = ipmitool.IPMIShellinaboxConsole()
-        self.boot = pxe.PXEBoot()
-        self.deploy = iscsi_deploy.ISCSIDeploy()
-        self.management = ipmitool.IPMIManagement()
-        self.inspect = inspector.Inspector.create_if_enabled(
-            'PXEAndIPMIToolDriver')
-        self.vendor = ipmitool.VendorPassthru()
-        self.raid = agent.AgentRAID()
-
-    @classmethod
-    def to_hardware_type(cls):
-        return 'ipmi', dict(_to_hardware_type(),
-                            console='ipmitool-shellinabox',
-                            deploy='iscsi')
-
-
-class PXEAndIPMIToolAndSocatDriver(PXEAndIPMIToolDriver):
-    """PXE + IPMITool + socat driver.
-
-    This driver implements the `core` functionality, combining
-    :class:`ironic.drivers.modules.ipmitool.IPMIPower` for power on/off
-    and reboot with
-    :class:`ironic.drivers.modules.iscsi_deploy.ISCSIDeploy` (for
-    image deployment) and with
-    :class:`ironic.drivers.modules.ipmitool.IPMISocatConsole`.
-    This driver uses the socat console interface instead of the shellinabox
-    one.
-    Implementations are in those respective
-    classes; this class is merely the glue between them.
-    """
-    def __init__(self):
-        PXEAndIPMIToolDriver.__init__(self)
-        self.console = ipmitool.IPMISocatConsole()
-
-    @classmethod
-    def to_hardware_type(cls):
-        return 'ipmi', dict(_to_hardware_type(),
-                            console='ipmitool-socat',
-                            deploy='iscsi')
-
-
-class AgentAndIPMIToolDriver(base.BaseDriver):
-    """Agent + IPMITool driver.
-
-    This driver implements the `core` functionality, combining
-    :class:`ironic.drivers.modules.ipmitool.IPMIPower` (for power on/off and
-    reboot) with :class:`ironic.drivers.modules.agent.AgentDeploy` (for
-    image deployment).
-    Implementations are in those respective classes; this class is merely the
-    glue between them.
-    """
-
-    def __init__(self):
-        self.power = ipmitool.IPMIPower()
-        self.boot = pxe.PXEBoot()
-        self.deploy = agent.AgentDeploy()
-        self.management = ipmitool.IPMIManagement()
-        self.console = ipmitool.IPMIShellinaboxConsole()
-        self.vendor = ipmitool.VendorPassthru()
-        self.raid = agent.AgentRAID()
-        self.inspect = inspector.Inspector.create_if_enabled(
-            'AgentAndIPMIToolDriver')
-
-    @classmethod
-    def to_hardware_type(cls):
-        return 'ipmi', dict(_to_hardware_type(),
-                            console='ipmitool-shellinabox',
-                            deploy='direct')
-
-
-class AgentAndIPMIToolAndSocatDriver(AgentAndIPMIToolDriver):
-    """Agent + IPMITool + socat driver.
-
-    This driver implements the `core` functionality, combining
-    :class:`ironic.drivers.modules.ipmitool.IPMIPower` (for power on/off and
-    reboot) with :class:`ironic.drivers.modules.agent.AgentDeploy` (for
-    image deployment) and with
-    :class:`ironic.drivers.modules.ipmitool.IPMISocatConsole`.
-    This driver uses the socat console interface instead of the shellinabox
-    one.
-    Implementations are in those respective classes; this class is merely the
-    glue between them.
-    """
-
-    def __init__(self):
-        AgentAndIPMIToolDriver.__init__(self)
-        self.console = ipmitool.IPMISocatConsole()
-
-    @classmethod
-    def to_hardware_type(cls):
-        return 'ipmi', dict(_to_hardware_type(),
-                            console='ipmitool-socat',
-                            deploy='direct')
diff --git a/ironic/drivers/modules/inspector.py b/ironic/drivers/modules/inspector.py
index d39acc06c2..6cd935a02b 100644
--- a/ironic/drivers/modules/inspector.py
+++ b/ironic/drivers/modules/inspector.py
@@ -74,21 +74,6 @@ def _get_client(context):
 class Inspector(base.InspectInterface):
     """In-band inspection via ironic-inspector project."""
 
-    @classmethod
-    def create_if_enabled(cls, driver_name):
-        """Create instance of Inspector if it's enabled.
-
-        Reports log warning with given driver_name if it's not.
-
-        :return: Inspector instance or None
-        """
-        if CONF.inspector.enabled:
-            return cls()
-        else:
-            LOG.info("Inspection via ironic-inspector is disabled in "
-                     "configuration for driver %s. To enable, change "
-                     "[inspector] enabled = True.", driver_name)
-
     def __init__(self):
         if not client:
             raise exception.DriverLoadError(
diff --git a/ironic/tests/unit/common/test_driver_factory.py b/ironic/tests/unit/common/test_driver_factory.py
index 83d22dd343..e1c281d9bb 100644
--- a/ironic/tests/unit/common/test_driver_factory.py
+++ b/ironic/tests/unit/common/test_driver_factory.py
@@ -421,13 +421,6 @@ class HardwareTypeLoadTestCase(db_base.DbTestCase):
         self.assertRaises(exception.DriverNotFound,
                           driver_factory.get_hardware_type, 'fake_agent')
 
-    def test_get_driver_or_hardware_type(self):
-        self.config(enabled_drivers=['pxe_ipmitool'])
-        hw_type = driver_factory.get_driver_or_hardware_type('fake-hardware')
-        self.assertIsInstance(hw_type, fake_hardware.FakeHardware)
-        driver = driver_factory.get_driver_or_hardware_type('pxe_ipmitool')
-        self.assertNotIsInstance(driver, fake_hardware.FakeHardware)
-
     def test_get_driver_or_hardware_type_missing(self):
         self.assertRaises(exception.DriverNotFound,
                           driver_factory.get_driver_or_hardware_type,
diff --git a/ironic/tests/unit/drivers/modules/test_inspector.py b/ironic/tests/unit/drivers/modules/test_inspector.py
index cd0ab04d94..ae5f1e8aab 100644
--- a/ironic/tests/unit/drivers/modules/test_inspector.py
+++ b/ironic/tests/unit/drivers/modules/test_inspector.py
@@ -15,8 +15,6 @@ import ironic_inspector_client as client
 import mock
 
 from ironic.common import context
-from ironic.common import driver_factory
-from ironic.common import exception
 from ironic.common import states
 from ironic.conductor import task_manager
 from ironic.drivers.modules import inspector
@@ -24,34 +22,6 @@ from ironic.tests.unit.db import base as db_base
 from ironic.tests.unit.objects import utils as obj_utils
 
 
-class DisabledTestCase(db_base.DbTestCase):
-    def _do_mock(self):
-        # NOTE(dtantsur): fake driver always has inspection, using another one
-        self.config(enabled_drivers=['pxe_ipmitool'])
-        self.driver = driver_factory.get_driver("pxe_ipmitool")
-
-    def test_disabled(self):
-        self.config(enabled=False, group='inspector')
-        self._do_mock()
-        self.assertIsNone(self.driver.inspect)
-        # Direct loading of the class is still possible
-        inspector.Inspector()
-
-    def test_enabled(self):
-        self.config(enabled=True, group='inspector')
-        self._do_mock()
-        self.assertIsNotNone(self.driver.inspect)
-
-    @mock.patch.object(inspector, 'client', None)
-    def test_init_inspector_not_imported(self):
-        self.assertRaises(exception.DriverLoadError,
-                          inspector.Inspector)
-
-    def test_init_ok(self):
-        self.config(enabled=True, group='inspector')
-        inspector.Inspector()
-
-
 @mock.patch('ironic.common.keystone.get_adapter', autospec=True)
 @mock.patch('ironic.common.keystone.get_service_auth', autospec=True,
             return_value=mock.sentinel.sauth)
@@ -132,17 +102,6 @@ class CommonFunctionsTestCase(BaseTestCase):
         res = self.iface.get_properties()
         self.assertEqual({}, res)
 
-    def test_create_if_enabled(self):
-        res = inspector.Inspector.create_if_enabled('driver')
-        self.assertIsInstance(res, inspector.Inspector)
-
-    @mock.patch.object(inspector.LOG, 'info', autospec=True)
-    def test_create_if_enabled_disabled(self, warn_mock):
-        self.config(enabled=False, group='inspector')
-        res = inspector.Inspector.create_if_enabled('driver')
-        self.assertIsNone(res)
-        self.assertTrue(warn_mock.called)
-
 
 @mock.patch.object(eventlet, 'spawn_n', lambda f, *a, **kw: f(*a, **kw))
 @mock.patch('ironic.drivers.modules.inspector._get_client', autospec=True)
diff --git a/ironic/tests/unit/drivers/test_ipmi.py b/ironic/tests/unit/drivers/test_ipmi.py
index 2a1f06281f..d302d60ecd 100644
--- a/ironic/tests/unit/drivers/test_ipmi.py
+++ b/ironic/tests/unit/drivers/test_ipmi.py
@@ -10,10 +10,7 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-import testtools
-
 from ironic.conductor import task_manager
-from ironic.drivers import ipmi
 from ironic.drivers.modules import agent
 from ironic.drivers.modules import ipmitool
 from ironic.drivers.modules import iscsi_deploy
@@ -102,52 +99,3 @@ class IPMIHardwareTestCase(db_base.DbTestCase):
             rescue_interface='agent')
         with task_manager.acquire(self.context, node.id) as task:
             self._validate_interfaces(task, rescue=agent.AgentRescue)
-
-
-class IPMIClassicDriversTestCase(testtools.TestCase):
-
-    def test_pxe_ipmitool_driver(self):
-        driver = ipmi.PXEAndIPMIToolDriver()
-
-        self.assertIsInstance(driver.power, ipmitool.IPMIPower)
-        self.assertIsInstance(driver.console, ipmitool.IPMIShellinaboxConsole)
-        self.assertIsInstance(driver.boot, pxe.PXEBoot)
-        self.assertIsInstance(driver.deploy, iscsi_deploy.ISCSIDeploy)
-        self.assertIsInstance(driver.management, ipmitool.IPMIManagement)
-        self.assertIsNone(driver.inspect)
-        self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru)
-        self.assertIsInstance(driver.raid, agent.AgentRAID)
-
-    def test_pxe_ipmitool_socat_driver(self):
-        driver = ipmi.PXEAndIPMIToolAndSocatDriver()
-
-        self.assertIsInstance(driver.power, ipmitool.IPMIPower)
-        self.assertIsInstance(driver.console, ipmitool.IPMISocatConsole)
-        self.assertIsInstance(driver.boot, pxe.PXEBoot)
-        self.assertIsInstance(driver.deploy, iscsi_deploy.ISCSIDeploy)
-        self.assertIsInstance(driver.management, ipmitool.IPMIManagement)
-        self.assertIsNone(driver.inspect)
-        self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru)
-        self.assertIsInstance(driver.raid, agent.AgentRAID)
-
-    def test_agent_ipmitool_driver(self):
-        driver = ipmi.AgentAndIPMIToolDriver()
-
-        self.assertIsInstance(driver.power, ipmitool.IPMIPower)
-        self.assertIsInstance(driver.console, ipmitool.IPMIShellinaboxConsole)
-        self.assertIsInstance(driver.boot, pxe.PXEBoot)
-        self.assertIsInstance(driver.deploy, agent.AgentDeploy)
-        self.assertIsInstance(driver.management, ipmitool.IPMIManagement)
-        self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru)
-        self.assertIsInstance(driver.raid, agent.AgentRAID)
-
-    def test_agent_ipmitool_socat_driver(self):
-        driver = ipmi.AgentAndIPMIToolAndSocatDriver()
-
-        self.assertIsInstance(driver.power, ipmitool.IPMIPower)
-        self.assertIsInstance(driver.console, ipmitool.IPMISocatConsole)
-        self.assertIsInstance(driver.boot, pxe.PXEBoot)
-        self.assertIsInstance(driver.deploy, agent.AgentDeploy)
-        self.assertIsInstance(driver.management, ipmitool.IPMIManagement)
-        self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru)
-        self.assertIsInstance(driver.raid, agent.AgentRAID)
diff --git a/playbooks/legacy/grenade-dsvm-ironic-multinode-multitenant/run.yaml b/playbooks/legacy/grenade-dsvm-ironic-multinode-multitenant/run.yaml
index ad333b4dae..aefb72b615 100644
--- a/playbooks/legacy/grenade-dsvm-ironic-multinode-multitenant/run.yaml
+++ b/playbooks/legacy/grenade-dsvm-ironic-multinode-multitenant/run.yaml
@@ -118,7 +118,9 @@
           export DEVSTACK_GATE_NEUTRON=1
           export DEVSTACK_GATE_VIRT_DRIVER=ironic
           export DEVSTACK_GATE_CONFIGDRIVE=1
-          export DEVSTACK_GATE_IRONIC_DRIVER=agent_ipmitool
+          export DEVSTACK_GATE_IRONIC_DRIVER=ipmi
+          export DEVSTACK_LOCAL_CONFIG+=$'\n'"IRONIC_DEFAULT_DEPLOY_INTERFACE=direct"
+
           export BRANCH_OVERRIDE="{{ zuul.override_checkout | default('default') }}"
           if [ "$BRANCH_OVERRIDE" != "default" ] ; then
               export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE
@@ -128,7 +130,7 @@
               export DEVSTACK_GATE_TLSPROXY=1
           fi
 
-          # agent_* drivers require Swift temporary URLs
+          # the direct deploy interface requires Swift temporary URLs
           export DEVSTACK_LOCAL_CONFIG+=$'\n'"SWIFT_ENABLE_TEMPURLS=True"
           export DEVSTACK_LOCAL_CONFIG+=$'\n'"SWIFT_TEMPURL_KEY=secretkey"
 
diff --git a/releasenotes/notes/no-classic-ipmi-7ec52a7b01e40536.yaml b/releasenotes/notes/no-classic-ipmi-7ec52a7b01e40536.yaml
new file mode 100644
index 0000000000..32ede28b47
--- /dev/null
+++ b/releasenotes/notes/no-classic-ipmi-7ec52a7b01e40536.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+  - |
+    The deprecated classic drivers ``pxe_ipmitool`` and ``agent_ipmitool``
+    have been removed. Please use the ``ipmi`` hardware type instead.
diff --git a/setup.cfg b/setup.cfg
index 899e8f03be..831bba4d1f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -52,12 +52,6 @@ ironic.dhcp =
     neutron = ironic.dhcp.neutron:NeutronDHCPApi
     none = ironic.dhcp.none:NoneDHCPApi
 
-ironic.drivers =
-    agent_ipmitool = ironic.drivers.ipmi:AgentAndIPMIToolDriver
-    agent_ipmitool_socat = ironic.drivers.ipmi:AgentAndIPMIToolAndSocatDriver
-    pxe_ipmitool = ironic.drivers.ipmi:PXEAndIPMIToolDriver
-    pxe_ipmitool_socat = ironic.drivers.ipmi:PXEAndIPMIToolAndSocatDriver
-
 ironic.hardware.interfaces.bios =
     fake = ironic.drivers.modules.fake:FakeBIOS
     no-bios = ironic.drivers.modules.noop:NoBIOS