clean的动作会在provide和delete阶段才会触发

从代码分析:

对节点执行的node provide/deleted/clean会先发送到ironicclient

ironicclient.call("node.set_provision_state", node.uuid,"deleted")
class Client(object):
self.node = node.NodeManager(self.http_client)
class NodeManager(base.CreateManager):
def set_provision_state(self, node_uuid, state, configdrive=None,
cleansteps=None, rescue_password=None)
在这个函数里面会构造一个http请求,包含一个url和一个body:
url = /v1/nodes/node_id/states/provision
patch = {'target': deleted}
然后发送给ironic-api

nova/virt/ironic/driver.py

ironic/api/controllers/v1/__init__.py  ------>>>
class Controller(rest.RestController): nodes = node.NodesController()
ports = port.PortsController()
portgroups = portgroup.PortgroupsController()
chassis = chassis.ChassisController()
drivers = driver.DriversController()
volume = volume.VolumeController()
lookup = ramdisk.LookupController()
heartbeat = ramdisk.HeartbeatController() ironic/api/controllers/v1/node.py ---->>>
class NodesController(rest.RestController):
states = NodeStatesController() ironic/api/controllers/v1/node.py ---->>>
class NodeStatesController(rest.RestController):
_custom_actions = {
'power': ['PUT'],
'provision': ['PUT'],
'raid': ['PUT'],
}
def provision(self, node_ident, target, configdrive=None,
clean_steps=None, rescue_password=None):
......
......
elif target == ir_states.DELETED:
pecan.request.rpcapi.do_node_tear_down(
pecan.request.context, rpc_node.uuid, topic) elif target == ir_states.VERBS['clean']:
if not clean_steps:
msg = (_('"clean_steps" is required when setting target '
'provision state to %s') % ir_states.VERBS['clean'])
raise wsme.exc.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
_check_clean_steps(clean_steps)
pecan.request.rpcapi.do_node_clean(
pecan.request.context, rpc_node.uuid, clean_steps, topic) elif target in PROVISION_ACTION_STATES:
pecan.request.rpcapi.do_provisioning_action(
pecan.request.context, rpc_node.uuid, target, topic) ironic/conductor/manager.py ----->>>
class ConductorManager(base_manager.BaseConductorManager):
......
......
def do_node_tear_down(self, context, node_id):
......
try:
task.process_event(
'delete',
callback=self._spawn_worker,
call_args=(self._do_node_tear_down, task,
task.node.provision_state),
err_handler=utils.provisioning_error_handler) def do_node_clean(self, context, node_id, clean_steps):
......
try:
task.process_event(
'clean',
callback=self._spawn_worker,
call_args=(self._do_node_clean, task, clean_steps),
err_handler=utils.provisioning_error_handler,
target_state=states.MANAGEABLE) def do_provisioning_action(self, context, node_id, action):
......
with task_manager.acquire(context, node_id, shared=False,
purpose='provision action %s'
% action) as task:
node = task.node
if (action == states.VERBS['provide'] and
node.provision_state == states.MANAGEABLE):
task.process_event(
'provide',
callback=self._spawn_worker,
call_args=(self._do_node_clean, task),
err_handler=utils.provisioning_error_handler)
return
最终都会调用到ironic-conductor的def _do_node_clean()函数,执行清理 ironic/conductor/manager.py ----->>>
class ConductorManager(base_manager.BaseConductorManager):
def _do_node_clean(self, task, clean_steps=None):
node = task.node
manual_clean = clean_steps is not None
clean_type = 'manual' if manual_clean else 'automated'
在这块就根据根据clean_setp判断清理是自动还是手动清理
如果在ironic.conf中automated_clean为false,且没有指定clean_steps,则直接进入available状态
if not manual_clean and not CONF.conductor.automated_clean:
# Skip cleaning, move to AVAILABLE.
node.clean_step = None
node.save()
task.process_event('done')
LOG.info('Automated cleaning is disabled, node %s has been '
'successfully moved to AVAILABLE state.', node.uuid)
return
ironic/drivers/modules/agent.py ----->>> class AgentDeploy(AgentDeployMixin, base.DeployInterface):
def prepare_cleaning(self, task):
return deploy_utils.prepare_inband_cleaning(
task, manage_boot=CONF.agent.manage_agent_boot)
引导ramdisk准备带内清理
ironic/drivers/modules/deploy_utils.py ---->>>
def prepare_inband_cleaning(task, manage_boot=True):
task.driver.network.add_cleaning_network(task)
agent_add_clean_params(task)
if manage_boot:
ramdisk_opts = build_agent_options(task.node)
task.driver.boot.prepare_ramdisk(task, ramdisk_opts) manager_utils.node_power_action(task, states.REBOOT)
return states.CLEANWAIT 等待节点启动,ipa发送心跳回来。ipa执行完所有clean步骤后,执行tear_down_cleaning
ironic/conductor/manager.py ----->>>
def _do_next_clean_step(self, task, step_index):
node = task.node
manual_clean = node.target_provision_state == states.MANAGEABLE
driver_internal_info = node.driver_internal_info
if step_index is None:
steps = []
else:
steps = driver_internal_info['clean_steps'][step_index:] LOG.info('Executing %(state)s on node %(node)s, remaining steps: '
'%(steps)s', {'node': node.uuid, 'steps': steps,
'state': node.provision_state}) ironic/drivers/modules/agent.py ----->>>
def tear_down_cleaning(self, task):
deploy_utils.tear_down_inband_cleaning(
task, manage_boot=CONF.agent.manage_agent_boot)
移除clean network,清理掉ipxe和dhcp相关的文件 ironic/drivers/modules/network/neutron.py --->>>
def remove_cleaning_network(self, task):
neutron.remove_ports_from_network(
task, self.get_cleaning_network_uuid(task))
for port in task.ports:
if 'cleaning_vif_port_id' in port.internal_info:
internal_info = port.internal_info
del internal_info['cleaning_vif_port_id']
port.internal_info = internal_info
port.save()

ipa和conductor通信部分见另外一篇文章,ipa和ironic-conductor交互

IPA加载后通过心跳触发ironic-conductor继续clean动作

ironic/drivers/modules/agent_base_vendor.py --->>>处理ipa返回的心跳
class HeartbeatMixin(object):
def heartbeat(self, task, callback_url, agent_version):
......
......
elif node.provision_state == states.CLEANWAIT:
self.continue_cleaning(task) ironic/drivers/modules/agent_base_vendor.py --->>>
class AgentDeployMixin(HeartbeatMixin):
def continue_cleaning(self, task, **kwargs):
.....
elif node.provision_state == states.CLEANWAIT:
_notify_conductor_resume_clean(task) ironic/drivers/modules/agent_base_vendor.py --->>>
def _notify_conductor_resume_clean(task):
uuid = task.node.uuid
rpc = rpcapi.ConductorAPI()
topic = rpc.get_topic_for(task.node)
task.release_resources()
rpc.continue_node_clean(task.context, uuid, topic=topic) ironic/conductor/rpcapi.py --->>>向conductor服务发出信号,启动下一个清理动作。
def continue_node_clean(self, context, node_id, topic=None):
cctxt = self.client.prepare(topic=topic or self.topic, version='1.27')
return cctxt.cast(context, 'continue_node_clean',
node_id=node_id) ironic/conductor/manager.py --->>>
def continue_node_clean(self, context, node_id):
......
task.spawn_after(
self._spawn_worker,
self._do_next_clean_step,
task, next_step_index) def _do_next_clean_step(self, task, step_index):
......
try:
result = interface.execute_clean_step(task, step)
如果该清理步骤未完成,则result为CLEANWAIT,该函数返回,等待下次心跳再次调用该函数
if result == states.CLEANWAIT:
LOG.info('Clean step %(step)s on node %(node)s being '
'executed asynchronously, waiting for driver.',
{'node': node.uuid, 'step': step})
target_state = states.MANAGEABLE if manual_clean else None
task.process_event('wait', target_state=target_state)
return
该步骤执行完毕后,会从driver_internal_info中将该清理步骤去掉
node.clean_step = None
driver_internal_info['clean_steps'] = None
driver_internal_info.pop('clean_step_index', None)
node.driver_internal_info = driver_internal_info
node.save() 传送给ipa来执行对应的clean command
ironic/drivers/modules/deploy_utils.py ---->>>
def agent_execute_clean_step(task, step):
client = agent_client.AgentClient()
ports = objects.Port.list_by_node_id(
task.context, task.node.id)
result = client.execute_clean_step(step, task.node, ports) ironic/drivers/modules/agent_client.py --->>>
class AgentClient(object):
def execute_clean_step(self, step, node, ports):
params = {
'step': step,
'node': node.as_dict(),
'ports': [port.as_dict() for port in ports],
'clean_version': node.driver_internal_info.get(
'hardware_manager_version')
}
return self._command(node=node,
method='clean.execute_clean_step',
params=params)
与ipa API交互
def _command(self, node, method, params, wait=False):
url = self._get_command_url(node)
body = self._get_command_body(method, params)
request_params = {
'wait': str(wait).lower()
try:
response = self.session.post(url, params=request_params, data=body)

ironic/drivers/modules/agent_base_vendor.py

IPA代码执行clean过程

ironic-python-agent/extentions/clean.py --->>>执行一个清理的步骤
class CleanExtension(base.BaseAgentExtension):
def execute_clean_step(self, step, node, ports, clean_version=None,**kwargs):
......
......
result = hardware.dispatch_to_managers(step['step'], node, ports)调用hardware的方法,按优先级获取硬件清理方法
清理磁盘
ironic_python_agent/hardware.py --->>>
class HardwareManager(object):
清除任何保存用户数据的设备
def erase_devices(self, node, ports):
erase_results = {}
block_devices = self.list_block_devices()
for block_device in block_devices:
result = dispatch_to_managers(
'erase_block_device', node=node, block_device=block_device)
erase_results[block_device.name] = result
return erase_results def erase_block_device(self, node, block_device):
if self._is_virtual_media_device(block_device):
LOG.info("Skipping the erase of virtual media device %s",
block_device.name)
return
try:
if self._ata_erase(block_device):判断设备是否支持安全擦除
return
.......
if self._shred_block_device(node, block_device):
return def _ata_erase(self, block_device):如果支持安全擦除则调用haparm命令进行擦除
security_lines = self._get_ata_security_lines(block_device)
......
if 'enabled' in security_lines:
try:
utils.execute('hdparm', '--user-master', 'u',
'--security-unlock', 'NULL', block_device.name)
security_lines = self._get_ata_security_lines(block_device)
def _shred_block_device(self, node, block_device):或者用shred擦除磁盘
info = node.get('driver_internal_info', {})
npasses = info.get('agent_erase_devices_iterations', 1)
args = ('shred', '--force') if info.get('agent_erase_devices_zeroize', True):
args += ('--zero', ) args += ('--verbose', '--iterations', str(npasses), block_device.name)

ironic-conductor与ipa交互clean部分代码分析的更多相关文章

  1. 例子Architecting Android…The clean way?----代码分析

    Presention层:   整个应用启动的时候,就执行依赖的初始化.编译项目之后,Dagger依赖框架使用ApplicationComponent生成一个DaggerApplicationCOmpo ...

  2. 在android程序中加入widget(窗口小部件)并与之交互的关键代码

    摘要: widget(窗口小部件)可以增强应用程序的交互性, 是很多应用中都会用到的功能,本文不求大而全,但是会给出程序与widget交互的关键代码 正文: 其实widget是嵌入(embedded) ...

  3. delphi 一个线程和主界面的交互的演示代码

    求一个线程和主界面的交互的演示代码求一个线程和主界面的交互的演示代码.线程和主界面处于两个Unit.线程中的user中不能引用主窗口.我只是想学习一下,线程和主界面交互的方法.去网上查了好几天资料,能 ...

  4. Django与JS交互的示例代码-django js 获取 python 字典-Django 前后台的数据传递

    Django与JS交互的示例代码 Django 前后台的数据传递 https://www.cnblogs.com/xibuhaohao/p/10192052.html 应用一:有时候我们想把一个 li ...

  5. 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)

    构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...

  6. wifi display代码 分析

    转自:http://blog.csdn.net/lilian0118/article/details/23168531 这一章中我们来看Wifi Display连接过程的建立,包含P2P的部分和RTS ...

  7. lighttpd与fastcgi+cgilua原理、代码分析与安装

    原理 http://www.cnblogs.com/skynet/p/4173450.html 快速通用网关接口(Fast Common Gateway Interface/FastCGI)是通用网关 ...

  8. AngularJS PhoneCat代码分析

    转载自:http://www.tuicool.com/articles/ym6Jfen AngularJS 官方网站提供了一个用于学习的示例项目:PhoneCat.这是一个Web应用,用户可以浏览一些 ...

  9. 使用 Gradle 插件进行代码分析(转)

    代码分析在大多数项目中通常是作为最后一个步骤(如果做了的话)完成的.其通常难以配置及与现有代码整合. 本文旨在勾勒出使用 Gradle 整合 PMD 与 FindBugs 的步骤,并将其与一个现有的 ...

随机推荐

  1. Uva 10791 最小公倍数的最小和 唯一分解定理

    题目链接:https://vjudge.net/contest/156903#problem/C 题意:给一个数 n ,求至少 2个正整数,使得他们的最小公倍数为 n ,而且这些数之和最小. 分析: ...

  2. 【转】startActivityForResult和setResult详解

    startActivityForResult与startActivity的不同之处在于:1.startActivity( ) 仅仅是跳转到目标页面,若是想跳回当前页面,则必须再使用一次startAct ...

  3. Design and Implementation of Global Path Planning System for Unmanned Surface Vehicle among Multiple Task Points

    Design and Implementation of Global Path Planning System for Unmanned Surface Vehicle among Multiple ...

  4. idea中使用maven方式使用jetty+cmd中使用Jetty运行(maven)Web项目

    进度条件:必须是web项目 一.使用idea 导入项目或者打开(如果有可以忽略) 导入项目 . 全部next 导入成功,进行打开pom文件加入插件 <plugins> <!-- je ...

  5. wordpress问题集锦

    1.内容不自动换行 找到对应的样式,添加如下代码,width根据具体情况修改. width:640px;white-space:normal;word-break:break-all;word-wra ...

  6. js 实现链表

    我们通常会在c++这类语言中学习到链表的概念,但是在js中由于我们可以动态的扩充数组,加之有丰富的原生api.我们通常并不需要实现链表结构.由于突发奇想,我打算用js实现一下: 首先我们要创建链表: ...

  7. window下绝对路径

    项目中配置文件(properties或yml)和项目是分离的,常见的配置方法如下: <profiles> <profile> <id>mas</id> ...

  8. cncert阅读报告

    信息安全阅读报告 Problem 1: 国家计算机网络应急技术处理协调中心(简称“国家互联网应急中心”,英文缩写为“CNCERT”或“CNCERT/CC”)作为我国非政府层面网络安全应急体系核心技术协 ...

  9. tar工具(打包,压缩)

    tar工具(打包,压缩)========================= tar打包工具 -c:表示建立一个tar包或者压缩文件包-x:表示解包或者解压缩-v:表示可视化-f: 后面跟文件名(即-f ...

  10. JavaScript---ECMA对象

    1.对象的概念及分类 1.1 ECMAScript中没有类,但定义了“对象”,逻辑上等价于其他程序设计语言中的类. var o = new Object(); 1.2 本地对象(native obje ...