114
123
return properties
126
class BaseInterface(object):
127
"""A base interface implementing common functions for Driver Interfaces."""
128
interface_type = 'base'
130
def __new__(cls, *args, **kwargs):
131
# Get the list of clean steps when the interface is initialized by
132
# the conductor. We use __new__ instead of __init___
133
# to avoid breaking backwards compatibility with all the drivers.
134
# We want to return all steps, regardless of priority.
135
instance = super(BaseInterface, cls).__new__(cls, *args, **kwargs)
136
instance.clean_steps = []
137
for n, method in inspect.getmembers(instance, inspect.ismethod):
138
if getattr(method, '_is_clean_step', False):
139
# Create a CleanStep to represent this method
140
step = {'step': method.__name__,
141
'priority': method._clean_step_priority,
142
'interface': instance.interface_type}
143
instance.clean_steps.append(step)
144
LOG.debug('Found clean steps %(steps)s for interface %(interface)s',
145
{'steps': instance.clean_steps,
146
'interface': instance.interface_type})
149
def get_clean_steps(self, task):
150
"""Get a list of (enabled and disabled) clean steps for the interface.
152
This function will return all clean steps (both enabled and disabled)
153
for the interface, in an unordered list.
155
:param task: A TaskManager object, useful for interfaces overriding
157
:returns: A list of clean step dictionaries
159
return self.clean_steps
161
def execute_clean_step(self, task, step):
162
"""Execute the clean step on task.node.
164
A clean step should take a single argument: a TaskManager object.
165
A step can be executed synchronously or asynchronously. A step should
166
return None if the method has completed synchronously or
167
states.CLEANING if the step will continue to execute asynchronously.
168
If the step executes asynchronously, it should issue a call to the
169
'continue_node_clean' RPC, so the conductor can begin the next
172
:param task: A TaskManager object
173
:param step: The clean step dictionary representing the step to execute
174
:returns: None if this method has completed synchronously, or
175
states.CLEANING if the step will continue to execute
178
return getattr(self, step['step'])(task)
117
181
@six.add_metaclass(abc.ABCMeta)
118
class DeployInterface(object):
182
class DeployInterface(BaseInterface):
119
183
"""Interface for deploy-related actions."""
184
interface_type = 'deploy'
121
186
@abc.abstractmethod
122
187
def get_properties(self):
217
282
:param task: a TaskManager instance containing the node to act on.
285
def prepare_cleaning(self, task):
286
"""Prepare the node for cleaning or zapping tasks.
288
For example, nodes that use the Ironic Python Agent will need to
289
boot the ramdisk in order to do in-band cleaning and zapping tasks.
291
If the function is asynchronous, the driver will need to handle
292
settings node.driver_internal_info['clean_steps'] and node.clean_step,
293
as they would be set in ironic.conductor.manager._do_node_clean,
294
but cannot be set when this is asynchronous. After, the interface
295
should make an RPC call to continue_node_cleaning to start cleaning.
297
NOTE(JoshNang) this should be moved to BootInterface when it gets
300
:param task: a TaskManager instance containing the node to act on.
301
:returns: If this function is going to be asynchronous, should return
302
`states.CLEANING`. Otherwise, should return `None`. The interface
303
will need to call _get_cleaning_steps and then RPC to
304
continue_node_cleaning
308
def tear_down_cleaning(self, task):
309
"""Tear down after cleaning or zapping is completed.
311
Given that cleaning or zapping is complete, do all cleanup and tear
312
down necessary to allow the node to be deployed to again.
314
NOTE(JoshNang) this should be moved to BootInterface when it gets
317
:param task: a TaskManager instance containing the node to act on.
221
322
@six.add_metaclass(abc.ABCMeta)
222
class PowerInterface(object):
323
class PowerInterface(BaseInterface):
223
324
"""Interface for power-related actions."""
325
interface_type = 'power'
225
327
@abc.abstractmethod
226
328
def get_properties(self):
453
555
dmeta = getattr(ref, '_driver_metadata', None)
455
557
if vmeta is not None:
456
vmeta.metadata['func'] = ref
457
inst.vendor_routes.update({vmeta.method: vmeta.metadata})
558
metadata = copy.deepcopy(vmeta.metadata)
559
metadata['func'] = ref
560
inst.vendor_routes.update({vmeta.method: metadata})
459
562
if dmeta is not None:
460
dmeta.metadata['func'] = ref
461
inst.driver_routes.update({dmeta.method: dmeta.metadata})
563
metadata = copy.deepcopy(dmeta.metadata)
564
metadata['func'] = ref
565
inst.driver_routes.update({dmeta.method: metadata})
715
@six.add_metaclass(abc.ABCMeta)
716
class InspectInterface(object):
717
"""Interface for inspection-related actions."""
720
def get_properties(self):
721
"""Return the properties of the interface.
723
:returns: dictionary of <property name>:<property description> entries.
727
def validate(self, task):
728
"""Validate the driver-specific inspection information.
730
If invalid, raises an exception; otherwise returns None.
732
:param task: a task from TaskManager.
733
:raises: InvalidParameterValue
734
:raises: MissingParameterValue
738
def inspect_hardware(self, task):
741
Inspect hardware to obtain the essential & additional hardware
744
:param task: a task from TaskManager.
745
:raises: HardwareInspectionFailure, if unable to get essential
747
:returns: resulting state of the inspection i.e. states.MANAGEABLE
752
def clean_step(priority):
753
"""Decorator for cleaning and zapping steps.
755
If priority is greater than 0, the function will be executed as part of the
756
CLEANING state for any node using the interface with the decorated clean
757
step. During CLEANING, a list of steps will be ordered by priority for all
758
interfaces associated with the node, and then execute_clean_step() will be
759
called on each step. Steps will be executed based on priority, with the
760
highest priority step being called first, the next highest priority
761
being call next, and so on.
763
Decorated clean steps should take a single argument, a TaskManager object.
765
Any step with this decorator will be available for ZAPPING, even if
766
priority is set to 0. Zapping steps will be executed in a similar fashion
767
to cleaning and with the same TaskManager object, but the priority ordering
768
is determined by the user when calling the zapping API.
770
Clean steps can be either synchronous or asynchronous. If the step is
771
synchronous, it should return `None` when finished, and the conductor will
772
continue on to the next step. If the step is asynchronous, the step should
773
return `states.CLEANING` to signal to the conductor. When the step is
774
complete, the step should make an RPC call to `continue_node_clean` to move
775
to the next step in cleaning.
779
class MyInterface(base.BaseInterface):
780
# CONF.example_cleaning_priority should be an int CONF option
781
@base.clean_step(priority=CONF.example_cleaning_priority)
782
def example_cleaning(self, task):
785
:param priority: an integer priority, should be a CONF option
788
func._is_clean_step = True
789
func._clean_step_priority = priority
610
794
def driver_periodic_task(parallel=True, **other):
611
795
"""Decorator for a driver-specific periodic task.