- 运维
- 配置管理
- 后端
【免费下载链接】salt
Software to automate the management and configuration of infrastructure and applications at scale.
本指南面向希望在 Salt 中快速探测目标机器硬件信息、并按 udev 属性筛选磁盘设备的运维与平台工程师。文章围绕 Salt 官方文档中
devinfo模块(doc/ref/modules/all/salt.modules.devinfo.rst,其内容由 salt/modules/devinfo.py 承载)展开,介绍devinfo.filter与devinfo.hwinfo两个公开执行函数的全部参数、CLI 用法与返回值结构,并结合模块源码与单元测试(tests/pytests/unit/modules/test_devinfo.py)解释其底层实现,使读者读完能直接写出可用的硬件筛选与探测命令。
模块概述与适用平台
devinfo是 Salt 的硬件信息探测执行模块,通过执行系统自带的hwinfo与udevadm命令,将硬件信息转化为结构化字典返回给 Salt 调用方。从 salt/modules/devinfo.py 的模块头可以看到:
- maintainer:Alberto Planas(aplanas@suse.com)
- maturity:new(较新的模块)
- depends:None(模块本身无硬性依赖,但依赖系统存在
hwinfo命令) - platform:Linux
因此devinfo只在 Linux 平台生效,且在目标 minion 上需要安装hwinfo软件包(openSUSE、SUSE Linux Enterprise 与主流 Linux 发行版均提供该命令)。模块内部实际通过 salt.modules.cmdmod 调用外部命令,底层证据可见 salt/modules/devinfo.py 中cmd.run_stdout(cmd)的执行方式。
模块共暴露两个公开执行函数:
| 函数 | 作用 | 依赖 |
|---|---|---|
devinfo.filter | 按 udev 键值对筛选磁盘设备 | disksgrain 与udev.info执行模块 |
devinfo.hwinfo | 探测并汇总 BIOS/CPU/磁盘/内存/网络/分区等硬件信息 | 系统hwinfo命令 |
注意 salt/modules/devinfo.py 中的__func_alias__把内部函数filter_对外映射为filter,所以在 Salt 命令行与状态文件里使用的是devinfo.filter而非devinfo.filter_。
devinfo.filter:按 udev 属性筛选磁盘设备
功能与 CLI 用法
devinfo.filter返回一张按 udev 键值过滤后的设备列表:返回的设备必须匹配udev_in中声明的键值,且不匹配udev_ex中声明的键值。官方 CLI 示例如下:
salt '*' devinfo.filter udev_in='{"e.id_bus": "ata"}'上面的命令会返回所有挂在 ATA 总线上的磁盘设备。从 tests/pytests/unit/modules/test_devinfo.py 的test_devices用例可以印证筛选行为:
udev_in={"e.id_bus": "ata"}时返回["sda", "sr0"](硬盘与光驱均属于 ata 总线);udev_in={"e.id_bus": "usb"}时返回["sdb"];udev_in={"e.id_bus": "ata"}且udev_ex={"s": ["cdrom"]}时返回["sda"],说明排除了属于 cdrom 的sr0。
参数说明
| 参数 | 类型 | 含义 |
|---|---|---|
udev_in | dict | 设备 udev 信息中预期匹配的key: value字典,未传时视为{} |
udev_ex | dict | 设备 udev 信息中不允许出现的key: value字典(排除条件),未传时视为{} |
udev_in/udev_ex中的 key 是小写、以点连接的字符串,表示设备 udev 信息字典中的一条路径。例如e.id_bus对应udev['E']['ID_BUS']。如果设备 udev 信息中某个值本身是列表,算法会检查"至少有一项与参数值中的某一项相同"。
键路径解析原理:_udev
点分键的解析由内部函数_udev完成,见 salt/modules/devinfo.py:key.partition(".")每次只取最前一段,将其转为大写后到当前层字典中取值,再对剩余部分递归;键为空时直接返回整棵字典;路径中断或值不是字典时返回字符串"n/a"。单元测试 tests/pytests/unit/modules/test_devinfo.py 覆盖了这些分支:
assert devinfo._udev({"A": {"B": 1}}, "a.b") == 1 assert devinfo._udev({"A": {"B": 1}}, "A.B") == 1 assert devinfo._udev({"A": {"B": 1}}, "a.c") == "n/a" assert devinfo._udev({"A": [1, 2]}, "a.b") == "n/a" assert devinfo._udev({"A": {"B": 1}}, "") == {"A": {"B": 1}}匹配规则原理:_match
_match(salt/modules/devinfo.py)把匹配条件与设备值分别转为集合后求交集:只要存在交集即视为命中(res = res and (value & udev_value))。若取到的设备值是字典(说明键路径未落到叶子节点),会记录一条 warning 日志并跳过该项匹配。对应测试见 tests/pytests/unit/modules/test_devinfo.py。
完整执行流程
filter_的实现(salt/modules/devinfo.py)分为四步:
- 从
__grains__["disks"]拿到本机全部磁盘设备名(该 grain 由核心 grain 模块 salt/grains/core.py 在 minion 启动时收集); - 对每个设备调用
__salt__"udev.info"获取一次 udev 信息,缓存在udev_info字典中; - 分别计算满足
udev_in的设备集合与满足udev_ex的设备集合; - 返回
sorted(udev_in 集合 - udev_ex 集合),即匹配且未被排除的设备的有序列表。
其中udev.info来自 salt/modules/udev.py,内部执行udevadm info --export --query=all,把E:前缀的行解析为环境变量子字典(E键),其余行按前缀归并为列表,返回结构形如{"S": [...], "E": {"ID_BUS": "ata", ...}}。这正是点分键中e.前缀与s.前缀对应的来源。
devinfo.hwinfo:探测并汇总硬件信息
功能与 CLI 用法
devinfo.hwinfo调用系统hwinfo命令探测硬件,并把输出解析为结构化字典。官方 CLI 示例如下:
salt '*' devinfo.hwinfo salt '*' devinfo.hwinfo items='["disk"]' short=no salt '*' devinfo.hwinfo items='["disk"]' short=no devices='["/dev/sda"]' salt '*' devinfo.hwinfo devices=/dev/sdadevices参数既支持列表('["/dev/sda"]')也支持单个字符串(/dev/sda)。
参数说明
| 参数 | 类型 | 默认值 | 含义 |
|---|---|---|---|
items | list/tuple/str | ['bios', 'cpu', 'disk', 'memory', 'network', 'partition'] | 要探测的硬件项列表,每项对应hwinfo --<item> |
short | bool | True | 只显示摘要;short=no时输出完整详情 |
listmd | bool | False | 是否同时报告 RAID 设备(映射为hwinfo --listmd) |
devices | list/tuple/str | None | 只显示指定设备的信息(映射为hwinfo --only <device>) |
若传入的items不是 list/tuple,源码会先包装成单元素列表(salt/modules/devinfo.py),devices同理,因此单值字符串也能直接使用。
命令构造与执行
hwinfo函数(salt/modules/devinfo.py)按如下方式构造命令:
cmd = ["hwinfo"] for item in items: cmd.append(f"--{item}") if short: cmd.append("--short") if listmd: cmd.append("--listmd") for device in devices: cmd.append(f"--only {device}")随后通过__salt__"cmd.run_stdout"执行(底层是 salt.modules.cmdmod.run_stdout 的封装),再调用_hwinfo_parse把输出解析成字典存入result["hwinfo"]。
返回值结构
hwinfo的返回值由解析结果与三类 grain 汇总组成:
result["hwinfo"]:hwinfo命令解析后的结构化数据;- 当
items含bios时,附加result["bios grains"] = {"efi": ..., "efi-secure-boot": ...}(取自__grains__["efi"]与__grains__["efi-secure-boot"]); - 当
items含memory时,附加result["memory grains"] = {"mem_total": ...}(取自__grains__["mem_total"]); - 当
items含network时,附加result["network grains"],包含fqdn、ip_interfaces,非short模式还包含dns。
上述三个 grain 均在核心 grain 模块 salt/grains/core.py 中收集(mem_total见该文件第 699–703 行附近的mem_data,ip_interfaces见ip_interfaces()函数),因此devinfo.hwinfo相当于"系统hwinfo命令 + Salt 核心 grains"的组合视图。
摘要模式解析:_hwinfo_parse_short
当short=True(默认)时使用_hwinfo_parse_short(salt/modules/devinfo.py)解析。它以缩进区分层级:
- 缩进 4 个空格的续行归入上一个条目,并作为无序子项存入
current_result; - 缩进 2 个空格的
key value行解析为键值对; - 以冒号结尾的
key:行开启新的硬件段,值为空字典。
例如 tests/pytests/unit/modules/test_devinfo.py 中的摘要输出会被解析为{"cpu": {0: "...", 1: "..."}, "disk": {"/dev/fd0": "Disk", "/dev/sda": "QEMU HARDDISK"}, ...}这样的结构,其中无键名的多行条目依次使用递增整数作为键。
完整模式解析:_hwinfo_parse_full
当short=no时使用_hwinfo_parse_full(salt/modules/devinfo.py),把hwinfo的完整报告解析为多级嵌套字典。其核心规则包括:
- 以行首空格数决定层级(
level与缩进深度保持一致); - 顶层
NN: <描述>行创建段落,并把冒号后的首个子元素解析为key: value; [Created at ...]或无法解析的行落入当前段的Note键;I/O Port键统一改名为I/O Ports;Config Status的a=b, c=d形式解析为嵌套字典;Driver、Driver Modules去除引号并按,拆成列表;Tags、Device Files、Features按逗号拆成列表;- 键冲突时自动把多个值合并为列表(如多个
I/O Ports、多个Memory Range、多个Size); - 以
#开头的行视为新段落,如Handle、BIOS Info、System Info等段落会各自成为嵌套字典; - 光盘的
El Torito info被特殊解析为{"platform": ..., "bootable": "yes"/"no", ...}字典。
这些行为在测试中均有详尽断言,例如 tests/pytests/unit/modules/test_devinfo.py 对含光驱、软盘、硬盘三种存储设备的hwinfo --disk输出验证:Device Files、Features被解析为列表,El Torito info被解析为嵌套字典;tests/pytests/unit/modules/test_devinfo.py 验证了I/O Ports的列表合并与Config Status的字典化;tests/pytests/unit/modules/test_devinfo.py 验证了网卡段Attached to被解析为{"Handle": ...}。
典型实战场景
场景一:列出全部 ATA/SATA 磁盘
salt '*' devinfo.filter udev_in='{"e.id_bus": "ata"}'结合 tests/pytests/unit/modules/test_devinfo.py 的行为,可预期返回该主机上所有 ata 总线磁盘(含光驱等块设备)的有序列表。若只想保留硬盘、排除光驱,可追加排除条件:
salt '*' devinfo.filter udev_in='{"e.id_bus": "ata"}' udev_ex='{"s": ["cdrom"]}'场景二:按总线类型做设备分组与装机核对
利用udev_in的列表匹配语义(设备值与参数值任一交集即命中),可以一次筛选多种总线:
salt '*' devinfo.filter udev_in='{"e.id_bus": ["usb", "nvme"]}'该命令可用于装机后的硬件核对,确认 USB 存储与 NVMe 盘是否如预期出现。
场景三:定向探测某块磁盘的完整硬件详情
salt '*' devinfo.hwinfo items='["disk"]' short=no devices='["/dev/sda"]'只探测disk项、输出完整模式,并限定/dev/sda,返回值中的hwinfo键会包含该盘的型号、序列号、容量、设备文件别名、驱动等信息,适合在更换硬件或扩容前做详细备案。
场景四:快速获取主机整体硬件摘要
salt '*' devinfo.hwinfo默认探测bios/cpu/disk/memory/network/partition六项并输出摘要,同时附上bios grains、memory grains、network grains三个汇总段,适合做节点健康巡检的第一步。
依赖与使用前提
- 目标 minion 必须运行 Linux 且安装
hwinfo命令,否则cmd.run_stdout执行失败; devinfo.filter依赖disksgrain(minion 启动时收集,见 salt/grains/core.py)以及udev.info执行模块;后者要求系统安装udevadm(salt/modules/udev.py 的__virtual__会检查udevadm是否存在);hwinfo的输出格式可能因发行版/版本略有差异,_hwinfo_parse_full对异常行会记录 error 日志并跳过,解析器的健壮性已由 tests/pytests/unit/modules/test_devinfo.py 中覆盖软盘、BIOS、系统、PCI 桥、以太网、存储、显卡、网络、磁盘、键盘、鼠标、CPU、网卡等十余种hwinfo段的测试验证。
结语
devinfo是 Salt 中把系统级硬件探测命令接入统一执行模块接口的典型实现:devinfo.filter用一套简洁的点分键约定复用udev.info的结构化数据,devinfo.hwinfo则在hwinfo文本输出之上提供摘要/完整两档解析并把常用核心 grains 一并汇总。结合 salt/modules/devinfo.py 源码与 tests/pytests/unit/modules/test_devinfo.py 单元测试,你可以放心地将上述命令用于资产盘点、装机核验与硬件巡检等场景;若需了解其数据来源,可进一步阅读 salt/modules/udev.py 与 salt/grains/core.py。
- 运维
- 配置管理
- 后端
【免费下载链接】salt
Software to automate the management and configuration of infrastructure and applications at scale.
相关推荐
Salt 的 mdadm_raid 执行模块实战指南:用 Salt 管理 Linux 软件 RAID
Salt 的 mdadm_raid 执行模块实战指南:用 Salt 管理 Linux 软件 RAID 本篇技术指南围绕 Salt 发行版中 raid 执行模块(
运维配置管理后端Salt smbios 执行模块:基于 DMIdecode 的 SMBIOS 硬件信息采集实战指南
Salt smbios 执行模块:基于 DMIdecode 的 SMBIOS 硬件信息采集实战指南 导读 salt.modules.smbios 是 Salt
运维配置管理后端Salt aliases 执行模块实战指南:用 Salt 批量管理邮件别名文件
Salt aliases 执行模块实战指南:用 Salt 批量管理邮件别名文件 导读 本文基于 Salt 仓库中的 aliases 执行模块文档 https:/
运维配置管理后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考