Simplify base interfaces in ironic.drivers.base
Move abstract definitions of get_properties and validate to BaseInterface and make all interfaces inherit it. This has a side effect of them getting clean steps methods, but they anyway won't be wired in due to a whitelist of interfaces in the conductor. The RAIDInterface contained a mistake: it didn't have an ABCMeta metaclass, so its @abstractmethod definitions didn't work. I've implemented get_properties for it to avoid breaking implementers. Also added interface_type to all interfaces for consistency and for future use in the driver composition work. Change-Id: Ia6708247a99ecdcf73d83e66350e8c309090b7d4 Partial-Bug: #1524745
This commit is contained in:
parent
8c6b8e2625
commit
565a0ed6b9
@ -171,6 +171,7 @@ class BareDriver(BaseDriver):
|
|||||||
self.core_interfaces.append('network')
|
self.core_interfaces.append('network')
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class BaseInterface(object):
|
class BaseInterface(object):
|
||||||
"""A base interface implementing common functions for Driver Interfaces."""
|
"""A base interface implementing common functions for Driver Interfaces."""
|
||||||
|
|
||||||
@ -182,6 +183,30 @@ class BaseInterface(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
interface_type = 'base'
|
interface_type = 'base'
|
||||||
|
"""Interface type, used for clean steps and logging."""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_properties(self):
|
||||||
|
"""Return the properties of the interface.
|
||||||
|
|
||||||
|
:returns: dictionary of <property name>:<property description> entries.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def validate(self, task):
|
||||||
|
"""Validate the driver-specific Node deployment info.
|
||||||
|
|
||||||
|
This method validates whether the 'driver_info' and/or 'instance_info'
|
||||||
|
properties of the task's node contains the required information for
|
||||||
|
this interface to function.
|
||||||
|
|
||||||
|
This method is often executed synchronously in API requests, so it
|
||||||
|
should not conduct long-running checks.
|
||||||
|
|
||||||
|
:param task: a TaskManager instance containing the node to act on.
|
||||||
|
:raises: InvalidParameterValue on malformed parameter(s)
|
||||||
|
:raises: MissingParameterValue on missing parameter(s)
|
||||||
|
"""
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
# Get the list of clean steps when the interface is initialized by
|
# Get the list of clean steps when the interface is initialized by
|
||||||
@ -252,32 +277,10 @@ class BaseInterface(object):
|
|||||||
return getattr(self, step['step'])(task)
|
return getattr(self, step['step'])(task)
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
|
||||||
class DeployInterface(BaseInterface):
|
class DeployInterface(BaseInterface):
|
||||||
"""Interface for deploy-related actions."""
|
"""Interface for deploy-related actions."""
|
||||||
interface_type = 'deploy'
|
interface_type = 'deploy'
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get_properties(self):
|
|
||||||
"""Return the properties of the interface.
|
|
||||||
|
|
||||||
:returns: dictionary of <property name>:<property description> entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the driver-specific Node deployment info.
|
|
||||||
|
|
||||||
This method validates whether the 'driver_info' property of the
|
|
||||||
task's node contains the required information for this driver to
|
|
||||||
deploy images to the node. If invalid, raises an exception; otherwise
|
|
||||||
returns None.
|
|
||||||
|
|
||||||
:param task: a TaskManager instance containing the node to act on.
|
|
||||||
:raises: InvalidParameterValue
|
|
||||||
:raises: MissingParameterValue
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def deploy(self, task):
|
def deploy(self, task):
|
||||||
"""Perform a deployment to the task's node.
|
"""Perform a deployment to the task's node.
|
||||||
@ -402,30 +405,9 @@ class DeployInterface(BaseInterface):
|
|||||||
{'node': task.node.uuid, 'driver': task.node.driver})
|
{'node': task.node.uuid, 'driver': task.node.driver})
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
class BootInterface(BaseInterface):
|
||||||
class BootInterface(object):
|
|
||||||
"""Interface for boot-related actions."""
|
"""Interface for boot-related actions."""
|
||||||
|
interface_type = 'boot'
|
||||||
@abc.abstractmethod
|
|
||||||
def get_properties(self):
|
|
||||||
"""Return the properties of the interface.
|
|
||||||
|
|
||||||
:returns: dictionary of <property name>:<property description> entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the driver-specific info for booting.
|
|
||||||
|
|
||||||
This method validates the driver-specific info for booting the
|
|
||||||
ramdisk and instance on the node. If invalid, raises an
|
|
||||||
exception; otherwise returns None.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
:returns: None
|
|
||||||
:raises: InvalidParameterValue
|
|
||||||
:raises: MissingParameterValue
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def prepare_ramdisk(self, task, ramdisk_params):
|
def prepare_ramdisk(self, task, ramdisk_params):
|
||||||
@ -482,32 +464,10 @@ class BootInterface(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
|
||||||
class PowerInterface(BaseInterface):
|
class PowerInterface(BaseInterface):
|
||||||
"""Interface for power-related actions."""
|
"""Interface for power-related actions."""
|
||||||
interface_type = 'power'
|
interface_type = 'power'
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get_properties(self):
|
|
||||||
"""Return the properties of the interface.
|
|
||||||
|
|
||||||
:returns: dictionary of <property name>:<property description> entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the driver-specific Node power info.
|
|
||||||
|
|
||||||
This method validates whether the 'driver_info' property of the
|
|
||||||
supplied node contains the required information for this driver to
|
|
||||||
manage the power state of the node. If invalid, raises an exception;
|
|
||||||
otherwise, returns None.
|
|
||||||
|
|
||||||
:param task: a TaskManager instance containing the node to act on.
|
|
||||||
:raises: InvalidParameterValue
|
|
||||||
:raises: MissingParameterValue
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def get_power_state(self, task):
|
def get_power_state(self, task):
|
||||||
"""Return the power state of the task's node.
|
"""Return the power state of the task's node.
|
||||||
@ -538,30 +498,9 @@ class PowerInterface(BaseInterface):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
class ConsoleInterface(BaseInterface):
|
||||||
class ConsoleInterface(object):
|
|
||||||
"""Interface for console-related actions."""
|
"""Interface for console-related actions."""
|
||||||
|
interface_type = "console"
|
||||||
@abc.abstractmethod
|
|
||||||
def get_properties(self):
|
|
||||||
"""Return the properties of the interface.
|
|
||||||
|
|
||||||
:returns: dictionary of <property name>:<property description> entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the driver-specific Node console info.
|
|
||||||
|
|
||||||
This method validates whether the 'driver_info' property of the
|
|
||||||
supplied node contains the required information for this driver to
|
|
||||||
provide console access to the Node. If invalid, raises an exception;
|
|
||||||
otherwise returns None.
|
|
||||||
|
|
||||||
:param task: a TaskManager instance containing the node to act on.
|
|
||||||
:raises: InvalidParameterValue
|
|
||||||
:raises: MissingParameterValue
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def start_console(self, task):
|
def start_console(self, task):
|
||||||
@ -591,27 +530,9 @@ class ConsoleInterface(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
class RescueInterface(BaseInterface):
|
||||||
class RescueInterface(object):
|
|
||||||
"""Interface for rescue-related actions."""
|
"""Interface for rescue-related actions."""
|
||||||
|
interface_type = "rescue"
|
||||||
@abc.abstractmethod
|
|
||||||
def get_properties(self):
|
|
||||||
"""Return the properties of the interface.
|
|
||||||
|
|
||||||
:returns: dictionary of <property name>:<property description> entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the rescue info stored in the node' properties.
|
|
||||||
|
|
||||||
If invalid, raises an exception; otherwise returns None.
|
|
||||||
|
|
||||||
:param task: a TaskManager instance containing the node to act on.
|
|
||||||
:raises: InvalidParameterValue
|
|
||||||
:raises: MissingParameterValue
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def rescue(self, task):
|
def rescue(self, task):
|
||||||
@ -714,8 +635,7 @@ def driver_passthru(http_methods, method=None, async=True, description=None,
|
|||||||
description=description, attach=attach)
|
description=description, attach=attach)
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
class VendorInterface(BaseInterface):
|
||||||
class VendorInterface(object):
|
|
||||||
"""Interface for all vendor passthru functionality.
|
"""Interface for all vendor passthru functionality.
|
||||||
|
|
||||||
Additional vendor- or driver-specific capabilities should be
|
Additional vendor- or driver-specific capabilities should be
|
||||||
@ -725,6 +645,7 @@ class VendorInterface(object):
|
|||||||
Methods decorated with @driver_passthru should be short-lived because
|
Methods decorated with @driver_passthru should be short-lived because
|
||||||
it is a blocking call.
|
it is a blocking call.
|
||||||
"""
|
"""
|
||||||
|
interface_type = "vendor"
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
super_new = super(VendorInterface, cls).__new__
|
super_new = super(VendorInterface, cls).__new__
|
||||||
@ -752,13 +673,6 @@ class VendorInterface(object):
|
|||||||
|
|
||||||
return inst
|
return inst
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get_properties(self):
|
|
||||||
"""Return the properties of the interface.
|
|
||||||
|
|
||||||
:returns: dictionary of <property name>:<property description> entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def validate(self, task, method=None, **kwargs):
|
def validate(self, task, method=None, **kwargs):
|
||||||
"""Validate vendor-specific actions.
|
"""Validate vendor-specific actions.
|
||||||
@ -788,29 +702,10 @@ class VendorInterface(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
|
||||||
class ManagementInterface(BaseInterface):
|
class ManagementInterface(BaseInterface):
|
||||||
"""Interface for management related actions."""
|
"""Interface for management related actions."""
|
||||||
interface_type = 'management'
|
interface_type = 'management'
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get_properties(self):
|
|
||||||
"""Return the properties of the interface.
|
|
||||||
|
|
||||||
:returns: dictionary of <property name>:<property description> entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the driver-specific management information.
|
|
||||||
|
|
||||||
If invalid, raises an exception; otherwise returns None.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
:raises: InvalidParameterValue
|
|
||||||
:raises: MissingParameterValue
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def get_supported_boot_devices(self, task):
|
def get_supported_boot_devices(self, task):
|
||||||
"""Get a list of the supported boot devices.
|
"""Get a list of the supported boot devices.
|
||||||
@ -899,31 +794,13 @@ class ManagementInterface(BaseInterface):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
class InspectInterface(BaseInterface):
|
||||||
class InspectInterface(object):
|
|
||||||
"""Interface for inspection-related actions."""
|
"""Interface for inspection-related actions."""
|
||||||
|
interface_type = 'inspect'
|
||||||
|
|
||||||
ESSENTIAL_PROPERTIES = {'memory_mb', 'local_gb', 'cpus', 'cpu_arch'}
|
ESSENTIAL_PROPERTIES = {'memory_mb', 'local_gb', 'cpus', 'cpu_arch'}
|
||||||
"""The properties required by scheduler/deploy."""
|
"""The properties required by scheduler/deploy."""
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get_properties(self):
|
|
||||||
"""Return the properties of the interface.
|
|
||||||
|
|
||||||
:returns: dictionary of <property name>:<property description> entries.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the driver-specific inspection information.
|
|
||||||
|
|
||||||
If invalid, raises an exception; otherwise returns None.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
:raises: InvalidParameterValue
|
|
||||||
:raises: MissingParameterValue
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def inspect_hardware(self, task):
|
def inspect_hardware(self, task):
|
||||||
"""Inspect hardware.
|
"""Inspect hardware.
|
||||||
@ -947,12 +824,12 @@ class RAIDInterface(BaseInterface):
|
|||||||
with open(RAID_CONFIG_SCHEMA, 'r') as raid_schema_fobj:
|
with open(RAID_CONFIG_SCHEMA, 'r') as raid_schema_fobj:
|
||||||
self.raid_schema = json.load(raid_schema_fobj)
|
self.raid_schema = json.load(raid_schema_fobj)
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def get_properties(self):
|
def get_properties(self):
|
||||||
"""Return the properties of the interface.
|
"""Return the properties of the interface.
|
||||||
|
|
||||||
:returns: dictionary of <property name>:<property description> entries.
|
:returns: dictionary of <property name>:<property description> entries.
|
||||||
"""
|
"""
|
||||||
|
return {}
|
||||||
|
|
||||||
def validate(self, task):
|
def validate(self, task):
|
||||||
"""Validates the RAID Interface.
|
"""Validates the RAID Interface.
|
||||||
@ -1035,7 +912,6 @@ class RAIDInterface(BaseInterface):
|
|||||||
return raid.get_logical_disk_properties(self.raid_schema)
|
return raid.get_logical_disk_properties(self.raid_schema)
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
|
||||||
class NetworkInterface(BaseInterface):
|
class NetworkInterface(BaseInterface):
|
||||||
"""Base class for network interfaces."""
|
"""Base class for network interfaces."""
|
||||||
|
|
||||||
|
@ -226,7 +226,14 @@ class CleanStepTestCase(base.TestCase):
|
|||||||
method_args_mock = mock.MagicMock(spec_set=[])
|
method_args_mock = mock.MagicMock(spec_set=[])
|
||||||
task_mock = mock.MagicMock(spec_set=[])
|
task_mock = mock.MagicMock(spec_set=[])
|
||||||
|
|
||||||
class TestClass(driver_base.BaseInterface):
|
class BaseTestClass(driver_base.BaseInterface):
|
||||||
|
def get_properties(self):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def validate(self, task):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class TestClass(BaseTestClass):
|
||||||
interface_type = 'test'
|
interface_type = 'test'
|
||||||
|
|
||||||
@driver_base.clean_step(priority=0)
|
@driver_base.clean_step(priority=0)
|
||||||
@ -240,7 +247,7 @@ class CleanStepTestCase(base.TestCase):
|
|||||||
def not_clean_method(self, task):
|
def not_clean_method(self, task):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TestClass2(driver_base.BaseInterface):
|
class TestClass2(BaseTestClass):
|
||||||
interface_type = 'test2'
|
interface_type = 'test2'
|
||||||
|
|
||||||
@driver_base.clean_step(priority=0)
|
@driver_base.clean_step(priority=0)
|
||||||
@ -254,7 +261,7 @@ class CleanStepTestCase(base.TestCase):
|
|||||||
def not_clean_method2(self, task):
|
def not_clean_method2(self, task):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TestClass3(driver_base.BaseInterface):
|
class TestClass3(BaseTestClass):
|
||||||
interface_type = 'test3'
|
interface_type = 'test3'
|
||||||
|
|
||||||
@driver_base.clean_step(priority=0, abortable=True, argsinfo={
|
@driver_base.clean_step(priority=0, abortable=True, argsinfo={
|
||||||
|
Loading…
Reference in New Issue
Block a user