fsm in ironic

hardware management 的技术发展了很多年,很多公司有自己的系统,deploy os 作为hardware management中最常用的功能之一,每个公司

可能都有几种自己的系统来完成这一操作,虽然实际的底层技术大同小异,但是每个系统封装的不同,实际扩展ironic时(ironic的确给出了一个框架,但是

有框架就有限制),需要对现有的框架有充分的认识,才能游刃有余,这其中比较晦涩的部分,当属:provision。

ironic/api/controller/v1/node.py中的provision中:

m = ir_states.machine.copy() #deep copy了一个fsm.FSM()
在ironic/common/states.py中,我们可以看到一堆类似这样的东西:

machine.add_state(MANAGEABLE, stable=True, **watchers)

machine.add_state(DEPLOYING, target=ACTIVE, **watchers)

#trace 进入 add_state:

    def add_state(self, state, on_enter=None, on_exit=None,  target=None, terminal=None, stable=False):

这样翻译一下add_state,对于state来说,进入和退出该state时候分别执行on_enter和on_exit方法,实际就是打了log,stable表示该状态是否是稳定状态,

即不会转移成为其他状态,只有稳定的状态才能成为target,而稳定的状态包括以下几个:manageable,available,active和error

machine.add_state(MANAGEABLE, stable=True, **watchers)
machine.add_state(AVAILABLE, stable=True, **watchers)
machine.add_state(ACTIVE, stable=True, **watchers)
machine.add_state(ERROR, stable=True, **watchers)

terminal是终止态,状态机终止,目前add_state中还没有terminal态。


machine.add_transition(AVAILABLE, DEPLOYING, 'deploy')

#trace进入add_transition:

 def add_transition(self, start, end, event):

这个也很简单,主体就是一句:

 self._transitions[start][event] = _Jump(end,  self._states[end]['on_enter'], self._states[start]['on_exit'])

翻译一下就是:状态机在start state下,遇到event,就跳转到end state,上面的例子中,available状态遇到deploy就成为deploying状态。

再一次特别需要指出的是:

ironic是一个发展很快的项目,特别是J版到K版,变化比较大,J版很多东西都不成熟,而在K版则改进了不少,在创建node的时候K版中:

        if 'uuid' not in values:
            values['uuid'] = uuidutils.generate_uuid()
        if 'power_state' not in values:
            values['power_state'] = states.NOSTATE
        if 'provision_state' not in values:
            # TODO(deva): change this to ENROLL
            values['provision_state'] = states.AVAILABLE #注意,在J版中,初始化provision state是NOSTATE,即“None”,K版会将NOSTATE变为available(后面会说)


接着上面provision函数:

 m.initialize(rpc_node.provision_state),即:

        self._current = _Jump(state, None, None)
        self._target_state = self._states[state]['target'] #_state['available']['target']为None

从_add_transitions中的状态变化可以看出,对于:

if not m.is_valid_event(ir_states.VERBS.get(target, target)):
            raise exception.InvalidStateRequested(
                    action=target, node=rpc_node.uuid,
                    state=rpc_node.provision_state)

available 遇到 deploy event 会变为deploying,而rebuild只有是当前provision 状态是active,或者deploy failed才会是valid event!这告诉我们什么时候

用active,什么时候用rebuild。


当target状态为active或者rebuild时,执行do_node_deploy,通过rpc call 会执行ironic/conductor/manager.py中的ConductorManager的方法:do_node_deploy!

with task_manager.acquire(context, node_id, shared=False) as task:

#得到task_manager,这其中做了几件事,trace code很容易知道:

1. task 初始化其fsm,该自动机有初始state和transition

2. 如果node不是shared,就reserve该node,对应的是node的reservation字段

3. 如果provision state是NOSTATE,就转变为available,在这儿做的!


继续trace这一过程:

1. 如果是node 是 maintenance状态就报错

2. 如果是rebuild则清空instance_info;

3. 更新driver_instance_info

4. check 该node对应的driver,power和deploy实现接口是否完整(其validation 函数执行是否通过)

5. 终于到了最关键的一步:

task.process_event(event,  callback=self._spawn_worker,
                                   call_args=(do_node_deploy, task,
                                              self.conductor.id,
                                              configdrive),
                                   err_handler=provisioning_error_handler)

中task_manager中的process_event方法,传进回调函数等等,在process_event中:

 self.fsm.process_event(event):trace FSM中的process_event,做了什么事?主要是得到target state:

replacement = self._transitions[current.name][event],得到replacement,event是rebuild或者active,会再次check,current.name是否可以通过event

进行状态转变,available遇到active变成deploying,active或者deploy failed遇到rebuild变成deploying,从前面add_state看到:

machine.add_state(DEPLOYING, target=ACTIVE, **watchers)

因此self._target_state变为active


6. 前面提到过使用python 的with 语法糖,是的task_manager的process_event传进去的回调函数最终会再次call do_node_deploy(此为ironic/conductor/task_manager

中的module 方法)

7.在module中的do_node_deploy中做了几件事:

   1. 一旦发生错误,不论是config drive造成的,prepare造成的,还是deploy造成的,处理”fail“ event,provision state则变成deploy failed

   2.  new_state = task.driver.deploy.deploy(task),调用driver 的deploy方法,返回一个状态,若状态是deploy complete则处理done,变成active状态,属于stable状态

        , 如果返回状态是deploy wait,则处理wait状态,self._target_state还是active,因此在deploy wait状态下会等待resume,fail,delete

   3.  bootloader安装成功后会和前面说的pass_deploy_info类似,image builder生成的image,对应的bootloader起来后,发一个rest call给ironic服务,调

        用vendor中的”pass_bootloader_install_info“方法,让task_manager处理”resume“事件;

   4. 和2中对应,FSM接收到resume后,再次变成deploying,等待接收done事件

    5. 验证bootloader的状态成功后,重启机器,deploy完成后,发送done事件,deploy成功



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值