在ironic 的工作流(修改及调试) 一中,通过pecan.request.rpcapi.xxxx 发送消息到消息队列,接收到消息后在对应conductor上执行ironic/conductor/manager.py中对应的方法。
我们看到manager.py中的方法基本都是这样的形式:
with task_manager.acquire(context, node_id,xxx) as task:
xxxxxxxxxxx
xxxxxxxxxxxx
ironic的框架根本就在这里,不同的厂商可以打自己的driver,在配置node信息得时候指明driver类型和所需信息即可,为什么不同的driver得以实现呢,追到根本就在
ironic/task_manager.py的类TaskManager中。
在此类中除了尝试初始化node, port, driver等信息外,对于一般的操作比如power on/off, management,console,ports, driver基本信息
task.driver.management.xxxx
task.driver.power.xxx
等操作完成,比较简单,可能看起来
def change_node_power_state(self, context, node_id, new_state):
with task_manager.acquire(context, node_id, shared=False) as task:
task.driver.power.validate(task)
# Set the target_power_state and clear any last_error, since we're
# starting a new operation. This will expose to other processes
# and clients that work is in progress.
if new_state == states.REBOOT:
task.node.target_power_state = states.POWER_ON
else:
task.node.target_power_state = new_state
task.node.last_error = None
task.node.save()
task.set_spawn_error_hook(power_state_error_handler,
task.node, task.node.power_state)
task.spawn_after(self._spawn_worker, utils.node_power_action,
task, new_state)
会不知道具体操作在哪里完成,并没有直接调用change_node_power_state的action,但在TaskManager中实现了:
def __exit__(self, exc_type, exc_val, exc_tb): #这是python中使用with....as...的语法糖,还有__enter__方法,在with/as 执行前后调用
而在__exit__方法中,起了一个线程执行utils.node_power_action动作,很多其他的操作也是通过这样的语法糖实现的。
对provision(deploy)这种不仅仅是数据库改变,而是需要获得target machine状态并根据状态执行不同操作的情况来说,自动机是常规选择,果然在TaskManager中:
self.fsm = states.machine.copy() #可以深拷贝也可以浅拷贝,目前看到的均是浅拷贝
FSM中状态的变更由process_event方法触发:
举例do_node_deploy:
ironic/conductor/manager.py的ConductorManager接到do_node_deploy的消息后,
调用do_node_deploy方法:
try:
task.process_event(event,
callback=self._spawn_worker,
call_args=(do_node_deploy, task,
self.conductor.id,
configdrive),
err_handler=provisioning_error_handler)
except exception.InvalidState:
raise exception.InvalidStateRequested(
action=event, node=task.node.uuid,
state=task.node.provision_state)
再调用manager.py的方法,同样名为do_node_deploy:
try:
task.driver.deploy.prepare(task)
except Exception as e:
with excutils.save_and_reraise_exception():
handle_failure(e, task,
_LW('Error while preparing to deploy to node %(node)s: '
'%(err)s'),
_("Failed to prepare to deploy. Error: %s"))
try:
new_state = task.driver.deploy.deploy(task)
except Exception as e:
with excutils.save_and_reraise_exception():
handle_failure(e, task,
_LW('Error in deploy of node %(node)s: %(err)s'),
_("Failed to deploy. Error: %s"))
状态获取与同步,待续