ironic.conductor.task_manager module

A context manager to perform a series of tasks on a set of resources.

TaskManager is a context manager, created on-demand to allow synchronized access to a node and its resources.

The TaskManager will, by default, acquire an exclusive lock on a node for the duration that the TaskManager instance exists. You may create a TaskManager instance without locking by passing “shared=True” when creating it, but certain operations on the resources held by such an instance of TaskManager will not be possible. Requiring this exclusive lock guards against parallel operations interfering with each other.

A shared lock is useful when performing non-interfering operations, such as validating the driver interfaces.

An exclusive lock is stored in the database to coordinate between ironic.conductor.manager instances, that are typically deployed on different hosts.

TaskManager methods, as well as driver methods, may be decorated to determine whether their invocation requires an exclusive lock.

The TaskManager instance exposes certain node resources and properties as attributes that you may access:

task.context

The context passed to TaskManager()

task.shared

False if Node is locked, True if it is not locked. (The ‘shared’ kwarg arg of TaskManager())

task.node

The Node object

task.ports

Ports belonging to the Node

task.portgroups

Portgroups belonging to the Node

task.volume_connectors

Storage connectors belonging to the Node

task.volume_targets

Storage targets assigned to the Node

task.driver

The Driver for the Node, or the Driver based on the ‘driver_name’ kwarg of TaskManager().

Example usage:

with task_manager.acquire(context, node_id, purpose='power on') as task:
    task.driver.power.power_on(task.node)

If you need to execute task-requiring code in a background thread, the TaskManager instance provides an interface to handle this for you, making sure to release resources when the thread finishes (successfully or if an exception occurs). Common use of this is within the Manager like so:

with task_manager.acquire(context, node_id, purpose='some work') as task:
    <do some work>
    task.spawn_after(self._spawn_worker,
                     utils.node_power_action, task, new_state)

All exceptions that occur in the current GreenThread as part of the spawn handling are re-raised. You can specify a hook to execute custom code when such exceptions occur. For example, the hook is a more elegant solution than wrapping the “with task_manager.acquire()” with a try..exception block. (Note that this hook does not handle exceptions raised in the background thread.):

def on_error(e):
    if isinstance(e, Exception):
        ...

with task_manager.acquire(context, node_id, purpose='some work') as task:
    <do some work>
    task.set_spawn_error_hook(on_error)
    task.spawn_after(self._spawn_worker,
                     utils.node_power_action, task, new_state)
class ironic.conductor.task_manager.TaskManager(context, node_id, shared=False, purpose='unspecified action', retry=True, patient=False, load_driver=True)[source]

Bases: object

Context manager for tasks.

This class wraps the locking, driver loading, and acquisition of related resources (eg, Node and Ports) when beginning a unit of work.

downgrade_lock()[source]

Downgrade the lock to a shared one.

load_driver()[source]
property node
property portgroups
property ports
process_event(event, callback=None, call_args=None, call_kwargs=None, err_handler=None, target_state=None, last_error=None)[source]

Process the given event for the task’s current state.

Parameters:
  • event – the name of the event to process

  • callback – optional callback to invoke upon event transition

  • call_args – optional args to pass to the callback method

  • call_kwargs – optional kwargs to pass to the callback method

  • err_handler – optional error handler to invoke if the callback fails, eg. because there are no workers available (err_handler should accept arguments node, prev_prov_state, and prev_target_state)

  • target_state – if specified, the target provision state for the node. Otherwise, use the target state from the fsm

  • last_error – last error to set on the node together with the state transition.

Raises:

InvalidState if the event is not allowed by the associated state machine

release_resources()[source]

Unlock a node and release resources.

If an exclusive lock is held, unlock the node. Reset attributes to make it clear that this instance of TaskManager should no longer be accessed.

resume_cleaning()[source]

A helper to resume cleaning with the right target state.

set_spawn_error_hook(_on_error_method, *args, **kwargs)[source]

Create a hook to handle exceptions when spawning a task.

Create a hook that gets called upon an exception being raised from spawning a background thread to do a task.

Parameters:
  • _on_error_method – a callable object, it’s first parameter should accept the Exception object that was raised.

  • args – additional args passed to the callable object.

  • kwargs – additional kwargs passed to the callable object.

spawn_after(_spawn_method, *args, **kwargs)[source]

Call this to spawn a thread to complete the task.

The specified method will be called when the TaskManager instance exits.

Parameters:
  • _spawn_method – a method that returns a GreenThread object

  • args – args passed to the method.

  • kwargs – additional kwargs passed to the method.

upgrade_lock(purpose=None, retry=None)[source]

Upgrade a shared lock to an exclusive lock.

Also reloads node object from the database. If lock is already exclusive only changes the lock purpose when provided with one.

Parameters:
  • purpose – optionally change the purpose of the lock

  • retry – whether to retry locking if it fails, the class-level value is used by default

Raises:

NodeLocked if an exclusive lock remains on the node after “node_locked_retry_attempts”

property volume_connectors
property volume_targets
ironic.conductor.task_manager.acquire(context, *args, **kwargs)[source]

Shortcut for acquiring a lock on a Node.

Parameters:

context – Request context.

Returns:

An instance of TaskManager.

ironic.conductor.task_manager.require_exclusive_lock(f)[source]

Decorator to require an exclusive lock.

Decorated functions must take a TaskManager as the first parameter. Decorated class methods should take a TaskManager as the first parameter after “self”.