当node节点state为manage时,可执行inspector
ironic node-set-provision-state <node_uuid> manage
ironic node-set-provision-state <node_uuid> inspect

inspect阶段

执行inspect后ironic会发送PUT请求到 /v1/nodes/{node_ident}/provision , ironic-api 收到这个请求后会根据 body 的 target 字段做处理:

class NodeStatesController(rest.RestController):
_custom_actions = {
'power': ['PUT'],
'provision': ['PUT'],
'raid': ['PUT'],
}
def get(self, node_ident):
.......
def raid(self, node_ident, target_raid_config):
......
def power(self, node_ident, target, timeout=None):
......
def provision(self, node_ident, target, configdrive=None,
clean_steps=None, rescue_password=None):
if target in (ir_states.ACTIVE, ir_states.REBUILD):#判断状态
rebuild = (target == ir_states.REBUILD)
pecan.request.rpcapi.do_node_deploy(context=pecan.request.context,
node_id=rpc_node.uuid,
rebuild=rebuild,
configdrive=configdrive,
topic=topic)
elif target == ir_states.VERBS['inspect']:#调用inspect_hardware方法
pecan.request.rpcapi.inspect_hardware(pecan.request.context, rpc_node.uuid, topic=topic)

ironic/api/controllers/v1/node.py

然后通过发送 http 请求 到 ironic-inspector。inspect 的具体实现是跟 driver 有关,在 driver.inspect.inspect_hardware 中

def inspect_hardware(self, task):
#检查硬件以获取硬件属性
eventlet.spawn_n(_start_inspection, task.node.uuid, task.context)
return states.INSPECTING def _start_inspection(node_uuid, context):
try:
_get_client(context).introspect(node_uuid)#调取_get_client函数,该函数调取keystone对inspector进行认证
def _get_client(context):
.......
return client.ClientV1(api_version=INSPECTOR_API_VERSION,
session=session,
inspector_url=inspector_url)#调取inspetor client

ironic/drivers/modules/inspector.py

class ClientV1(http.BaseClient):
#客户端V1版本
.......
#创建一个客户端
def __init__(self, **kwargs):
kwargs.setdefault('api_version', DEFAULT_API_VERSION)
super(ClientV1, self).__init__(**kwargs)
self.rules = RulesAPI(self.request)#获取自省规则 #启动节点自省
def introspect(self, uuid):
if not isinstance(uuid, six.string_types):
raise TypeError(
_("Expected string for uuid argument, got %r") % uuid) self.request('post', '/introspection/%s' % uuid)

ironic_inspector_client/v1.py

inspector处理阶段

@api('/v1/introspection/<node_id>',
rule="introspection:{}",
verb_to_rule_map={'GET': 'status', 'POST': 'start'},
methods=['GET', 'POST'])
def api_introspection(node_id):
if flask.request.method == 'POST':#如果请求是post,验证token,返回202,即接受请求
introspect.introspect(node_id,
token=flask.request.headers.get('X-Auth-Token'))#调取introspect函数,为节点启动硬件属性自省。
return '', 202
else:
node_info = node_cache.get_node(node_id)
return flask.json.jsonify(generate_introspection_status(node_info))

ironic-inspector/ironic_inspector/main.py

def introspect(node_id, token=None):
node_info = node_cache.start_introspection(node.uuid,#更新了ipmi信息,在attributes表里添加bmc_address信息
bmc_address=bmc_address,
ironic=ironic)
utils.executor().submit(_background_introspect, node_info, ironic) def _background_introspect(node_info, ironic):
......
......
node_info.acquire_lock()
_background_introspect_locked(node_info, ironic)#调用 _background_introspect做主机发现。 def _background_introspect_locked(node_info, ironic):
......
try:
ironic.node.set_boot_device(node_info.uuid, 'pxe',
persistent=False)
except Exception as exc:
LOG.warning('Failed to set boot device to PXE: %s',
exc, node_info=node_info)
try:
ironic.node.set_power_state(node_info.uuid, 'reboot')
except Exception as exc:
raise utils.Error(_('Failed to power on the node, check it\'s '
'power management configuration: %s'),
exc, node_info=node_info)

ironic_inspector/introspect.py

ipa阶段

class IronicPythonAgent(base.ExecuteCommandMixin):
......
......
def run(self):
self.started_at = _time()
hardware.load_managers()
if self.hardware_initialization_delay > 0:
LOG.info('Waiting %d seconds before proceeding',
self.hardware_initialization_delay)
time.sleep(self.hardware_initialization_delay)
if not self.standalone:
uuid = None
if cfg.CONF.inspection_callback_url:
uuid = inspector.inspect()#因配置了callback_url,跳转到inspect

ironic_python_agent/agent.py

def inspect():
....
if not CONF.inspection_callback_url:
LOG.info('Inspection is disabled, skipping')
return
collector_names = [x.strip() for x in CONF.inspection_collectors.split(',')
if x.strip()]
LOG.info('inspection is enabled with collectors %s', collector_names)
failures = utils.AccumulatedFailures(exc_class=errors.InspectionError)
data = {} try:
# 对应该文件中的collect_*函数,默认为default,对应collect_default
ext_mgr = extension_manager(collector_names)
collectors = [(ext.name, ext.plugin) for ext in ext_mgr]
except Exception as exc:
with excutils.save_and_reraise_exception():
failures.add(exc)
call_inspector(data, failures) for name, collector in collectors:
try:
# 例:此处为collect_default
collector(data, failures)
except Exception as exc:
failures.add('collector %s failed: %s', name, exc)
# 跳转到call_inspector函数,该函数用于发送data给inspector
resp = call_inspector(data, failures)
failures.raise_if_needed()
if resp is None:
LOG.info('stopping inspection, as inspector returned an error')
return
LOG.info('inspection finished successfully')
return resp.get('uuid') def collect_default(data, failures):
# 调用ironic_python_agent.hardware.py中的list_hardware_info函数
inventory = hardware.dispatch_to_managers('list_hardware_info')
# 添加到data中
data['inventory'] = inventory

ironic_python_agent/inspector.py

ipa 可以看到除了collect_default,还提供了collect_logs、collect_extra_hardware、collect_pci_devices_info三个函数,分别用于收集系统日志、收集benchmark、收集pci设备信息 
ironic_python_agent.hardware.py 可以看看collect_default收集了哪些信息

class HardwareManager(object):
......
.....
def list_hardware_info(self):
hardware_info = {}
hardware_info['interfaces'] = self.list_network_interfaces()#网卡
hardware_info['cpu'] = self.get_cpus()#cpu
hardware_info['disks'] = self.list_block_devices()#硬盘
hardware_info['memory'] = self.get_memory()#内存
hardware_info['bmc_address'] = self.get_bmc_address()#bmc地址
hardware_info['system_vendor'] = self.get_system_vendor_info()#系统厂商信息
hardware_info['boot'] = self.get_boot_info()#启动信息
return hardware_info#返回硬件信息

ironic_python_agent/hardware.py

ipa收集BM信息并将其发送给ipa-inspection-callback-url

@api('/v1/continue', rule="introspection:continue", is_public_api=True,
methods=['POST'])
def api_continue():
data = flask.request.get_json(force=True)#检查是否是json格式的数据
if not isinstance(data, dict):
raise utils.Error(_('Invalid data: expected a JSON object, got %s') %
data.__class__.__name__) logged_data = {k: (v if k not in _LOGGING_EXCLUDED_KEYS else '<hidden>')
for k, v in data.items()}
LOG.debug("Received data from the ramdisk: %s", logged_data,
data=data) return flask.jsonify(process.process(data))#跳转到process函数,处理来自ipa的自省数据

ironic_inspector/main.py

def process(introspection_data):
unprocessed_data = copy.deepcopy(introspection_data)
failures = []
_run_pre_hooks(introspection_data, failures)
node_info = _find_node_info(introspection_data, failures)#根据ipmi_address和macs获取inpsector node
if node_info:
node_info.acquire_lock()
......
utils.executor().submit(_store_unprocessed_data, node_info,
unprocessed_data)#多线程处理_store_unprocessed_data函数,存储数据
try:
node = node_info.node()#从node_info中提取node
.....
try:
result = _process_node(node_info, node, introspection_data) #跳转到_process_node函数,该函数会重复检查node信息 def _process_node(node_info, node, introspection_data):
ir_utils.check_provision_state(node)#检查node自省状态
_run_post_hooks(node_info, introspection_data)
_store_data(node_info, introspection_data)#存储数据,如ironic-inspector配置中store_data为none,则不存储 ironic = ir_utils.get_client()#调用ironic client
pxe_filter.driver().sync(ironic) node_info.invalidate_cache()#清除所有缓存的信息,以便下次重新加载
rules.apply(node_info, introspection_data)#对node应用规则 resp = {'uuid': node.uuid}
#结束inspect流程,调用_finish函数,该函数处理关闭电源的过程
utils.executor().submit(_finish, node_info, ironic, introspection_data,
power_off=CONF.processing.power_off)
return resp def _finish(node_info, ironic, introspection_data, power_off=True):
if power_off:
LOG.debug('Forcing power off of node %s', node_info.uuid)
try:
ironic.node.set_power_state(node_info.uuid, 'off')
except Exception as exc:
if node_info.node().provision_state == 'enroll':
LOG.info("Failed to power off the node in"
"'enroll' state, ignoring; error was "
"%s", exc, node_info=node_info,
data=introspection_data)
else:
msg = (_('Failed to power off node %(node)s, check '
'its power management configuration: '
'%(exc)s') % {'node': node_info.uuid, 'exc':
exc})
raise utils.Error(msg, node_info=node_info,
data=introspection_data)
LOG.info('Node powered-off', node_info=node_info,
data=introspection_data) node_info.finished(istate.Events.finish)
LOG.info('Introspection finished successfully',
node_info=node_info, data=introspection_data)

ironic_inspector.process.py

inspect流程的更多相关文章

  1. install ironic-inspector

    安装相应的包和组件 yum install openstack-ironic-inspector python-ironic-inspector-client -y 创建user openstack ...

  2. jQuery-1.9.1源码分析系列(十六)ajax——ajax处理流程以及核心函数

    先来看一看jQuery的ajax核心处理流程($.ajax) a. ajax( [url,] options )执行流程 第一步,为传递的参数做适配.url可以包含在options中 //传递的参数只 ...

  3. 利用Sonar规则结合WebStorm进行Code Inspect

    1.目的 在编写代码时会受到公司Sonar规则的限制,不想在编写完成后再对代码进行Inspect,回头再来一个个修正,费时费力. 那么,下面将通过优秀的WebStorm开发工具自身的CodeInspe ...

  4. chrome://inspect 移动前端调试方案(Android + Chrome 实现远程调试)

    一:背景通常情况我们调试移动端页面最常用的方法就是:切换pc端浏览器的userAgent来模拟手机或其他移动设备调试页面 然后用手机打开要调试的页面 刷新页面查看调试结果 但是这就存在两个问题 在pc ...

  5. Dockerfile与Docker构建流程解读

    摘要 本文主要讨论了对docker build的源码流程进行了梳理和解读,并分享了在制作Dockerfile过程中的一些实践经验,包括如何调试.优化和build中的一些要点.另外,还针对现有Docke ...

  6. PHP容器--Pimple运行流程浅析

    需要具备的知识点 闭包 闭包和匿名函数在PHP5.3.0中引入的. 闭包是指:创建时封装周围状态的函数.即使闭包所处的环境不存在了,闭包中封装的状态依然存在. 理论上,闭包和匿名函数是不同的概念.但是 ...

  7. Webpack系列-第三篇流程杂记

    系列文章 Webpack系列-第一篇基础杂记 Webpack系列-第二篇插件机制杂记 Webpack系列-第三篇流程杂记 前言 本文章个人理解, 只是为了理清webpack流程, 没有关注内部过多细节 ...

  8. asp.net core 2.0发布到IIS流程及报错解决方案

      我这是个新装的服务器,没有安装任何软件. 一.发布流程 1.安装AspNetCoreModule托管模块,同时会自动安装..net core runtime DotNetCore.2.0.8-Wi ...

  9. asyncio源码分析之基本执行流程

    基于async关键字的原生协程 # 定义一个简单的原生协程cor async def cor(): print('enter cor') print('exit cor') print(type(co ...

随机推荐

  1. BFS变换素数,POJ(3126)

    题目链接:http://poj.org/problem?id=3126 解题报告: #include <iostream> #include <queue> #include ...

  2. 【转】批处理命令 For循环命令详解!

    批处理for命令详解FOR这条命令基本上都被用来处理文本,但还有其他一些好用的功能!看看他的基本格式(这里我引用的是批处理中的格式,直接在命令行只需要一个%号)FOR 参数 %%变量名 IN (相关文 ...

  3. nodejs使用MYSQL连接池,断线重连

    两种方式解决1.你可以配置mysql的连接池 var mysql = require('mysql'); var pool = mysql.createPool({ host: 'localhost' ...

  4. Centos6.4环境下DNS服务器的搭建

    DNS服务器搭建很繁琐吗?给你个简单的招吧! 配置域主服务器 阶段: 1.在bind的主配置文件中添加该域 2.在/var/named中创建该域的zone文件 3.编辑zone文件,添加需要的信息 4 ...

  5. Ubuntu搜狗输入法无法输入中文等问题

    Linux版本的搜狗输入法经常崩溃,无法输入中文,今天作下记录,环境:Ubuntu14.04 64位 1.安装和卸载 Linux搜狗是基于框架fcitx的,先得安装框架Ubunt安装搜狗方法 也可以直 ...

  6. python-一切事物都是对象

    python:一切事物都是对象 开始接触python,在里面有一句话“一切事物都是对象”,那么如何来理解这句话呢,下面举简单的例子: a=1 b='hello't=(11,22,33) list1=[ ...

  7. element-UI时间控件:日期时间的选择范围的控制方法

    例:如一段已知的时间范围,为2018-10-01 - 2019-01-01 :当前为2018-07-09日,则今天以前的时间不能选择,以及2019-01-01以后的时间不能选:实现如下: <el ...

  8. 2、SpringBoot------数据转换

    开发工具:STS 代码下载链接:https://github.com/theIndoorTrain/Springboot/tree/083bb312526653d27ca56abf4f586e097c ...

  9. 微信小程序开发踩坑与总结 -

    原文链接:https://segmentfault.com/a/1190000008516296 前段时间把公司小程序项目开发完成了,所以来写写自己开发过程中碰到的问题和解决方法,以及用到的提高效率的 ...

  10. POJ2409 Let it Bead(Polya定理)

    Let it Bead Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6443   Accepted: 4315 Descr ...