SaltStack中Jinja2 set语句依赖状态失败及IPMI命令调用问题求助
解决方案:SaltStack中Jinja2变量依赖状态执行的替代方案
核心问题分析
Jinja2的set语句在SaltStack的sls文件渲染阶段就会执行,远早于pkg.installed这类状态模块的执行流程,因此无法直接让set语句依赖状态的安装结果。
替代方案1:将命令执行放入状态,结果存入Grains
把IPMI命令的执行逻辑放到状态中,依赖ipmitool安装完成后再执行,然后将结果写入Grains,后续需要使用变量时直接从Grains读取:
install-ipmi: pkg.installed: - name: ipmitool get-ipmi-data: cmd.run: - name: ipmitool -I lanplus -H hostip -U username -P password raw 0x0c 0x02 0x01 0x05 0x00 0x00 > /tmp/ipmi_result - require: - pkg: install-ipmi store-ipmi-grain: grains.setval: - name: ipmi_custom_data - value: {{ salt['cmd.cat']('/tmp/ipmi_result').strip() }} - require: - cmd: get-ipmi-data
后续使用变量的示例:
{% set var = grains.get('ipmi_custom_data', '') %}
替代方案2:修复内置IPMI模块调用,放入状态执行
如果内置ipmi.raw_command无返回数据,先检查参数是否完整(需明确指定bridge、host等参数),再将模块调用放到状态中执行,依赖安装完成后存储结果:
install-ipmi: pkg.installed: - name: ipmitool execute-ipmi-raw: module.run: - name: ipmi.raw_command - bridge: lanplus - host: hostip - username: username - password: password - command: 0x0c 0x02 0x01 0x05 0x00 0x00 - require: - pkg: install-ipmi store-ipmi-result: grains.setval: - name: ipmi_raw_result - value: {{ salt['ipmi.raw_command'](bridge='lanplus', host='hostip', username='username', password='password', command='0x0c 0x02 0x01 0x05 0x00 0x00') | default('', true) }} - require: - module: execute-ipmi-raw
替代方案3:分阶段执行(先安装,再获取数据)
通过两次Salt调用拆分流程:
- 先执行ipmitool安装状态:
salt 'target-minion' state.apply install-ipmi
- 单独执行IPMI命令并获取结果:
salt 'target-minion' cmd.run "ipmitool -I lanplus -H hostip -U username -P password raw 0x0c 0x02 0x01 0x05 0x00 0x00" --out=json > ipmi_result.json
后续可将结果导入Pillar,或在其他状态中读取该文件内容。
关键注意事项
- 绝对避免在Jinja2渲染阶段调用依赖状态执行的模块/命令,渲染流程远早于状态执行。
- 敏感信息(如IPMI密码)建议用SaltStack的Pillar加密或环境变量存储,不要明文写入sls文件。
内容的提问来源于stack exchange,提问作者Tal Brown
相关产品推荐
相关产品推荐

