一。结构体TaskManager:
需要对节点加锁,可以是共享或者自旋锁,共享所主要是read-only或则没有破坏性的action(主要考虑其他线程的操作)。
异常raises:
@ DriverNotFound
@ InterfaceNotFoundInEntrypoint
@ NodeNotFound
@ NodeLocked
暴露节点资源和属性:
@ task.context
@ task.shared
@ task.node
@ task.ports
@ task.portgroups
@ task.volume_connectors
@ task.volume_targets
@ task.driver
二。TaskManager使用方法:
使用方法如下:
with task_manager.acquire(context, node_id, purpose='power on') as task:
task.driver.power.power_on(task.node)
如果需要后端线程执行:
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)
如果异常发生了可以使用hook函数
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)
三。TaskManager代码分析:
主要函数 process_event(self, event, callback=None, call_args=None, call_kwargs=None, err_handler=None, target_state=None)
处理任务当前状态事件
# save previous states and event
self._prev_provision_state = self.node.provision_state
self._prev_target_provision_state = self.node.target_provision_state
self._event = event
@ 保存先前的状态,保存事件event
if not callback and self.fsm.is_stable(self.node.provision_state):
self.node.target_provision_state = states.NOSTATE
else:
self.node.target_provision_state = self.fsm.target_state
@ 设置target_provision_state,没有需要处理states.NOSTATE
# set up the async worker
if callback:
# clear the error if we're going to start work in a callback
self.node.last_error = None
if call_args is None:
call_args = ()
if call_kwargs is None:
call_kwargs = {}
self.spawn_after(callback, *call_args, **call_kwargs)
@ 建立一个异步worker,主要内容:
if callback is None:
self._notify_provision_state_change()
@ 没有callback,会通知provision_state_change
函数: _notify_provision_state_change主要逻辑如下:
根据pre_state和new_state是不是stable,得到status和level
state = node.provision_state
prev_state = self._prev_provision_state
new_unstable = state in states.UNSTABLE_STATES
prev_unstable = prev_state in states.UNSTABLE_STATES
level = fields.NotificationLevel.INFO
if self._event in ('fail', 'error'):
status = fields.NotificationStatus.ERROR
level = fields.NotificationLevel.ERROR
elif (prev_unstable, new_unstable) == (False, True):
status = fields.NotificationStatus.START
elif (prev_unstable, new_unstable) == (True, False):
status = fields.NotificationStatus.END
else:
status = fields.NotificationStatus.SUCCESS
notify.emit_provision_set_notification(
task, level, status, self._prev_provision_state,
self._prev_target_provision_state, self._event)
def emit_power_state_corrected_notification(task, from_power):
"""Helper for conductor sending a node power state corrected notification.
When ironic detects that the actual power state on a bare metal hardware
is different from the power state on an ironic node (DB), the ironic
node's power state is corrected to be that of the bare metal hardware.
A notification is emitted about this after the database is updated to
reflect this correction.
:param task: a TaskManager instance.
:param from_power: the power state of the node before this change was
detected
"""
_emit_conductor_node_notification(
task,
node_objects.NodeCorrectedPowerStateNotification,
node_objects.NodeCorrectedPowerStatePayload,
'power_state_corrected',
fields.NotificationLevel.INFO,
fields.NotificationStatus.SUCCESS,
from_power=from_power
)
@ _emit_conductor_node_notification