关于 infrahub-converting-netbox-device-types
此技能使用内置 Python 脚本和映射配置,将 NetBox 设备类型 YAML 转为可复用的 Infrahub 对象模板。适用于从公开库或 NetBox 导出导入设备模型,并报告目标 Schema 无法承载的数据。
主要功能
- 01将设备类型 YAML 转为 Infrahub 模板
- 02支持模块类型和组件端口
- 03通过 Schema 专用配置映射字段
- 04从 NetBox 实例导出设备类型
- 05生成转换覆盖率报告
适用场景
- 01用厂商设备型号初始化 Infrahub
- 02为实验室拓扑转换指定设备类型
- 03在库或 Schema 更新后重新转换
- 04为自定义 Infrahub Schema 编写映射
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ opsmill/ infrahub-skills --skill infrahub-converting-netbox-device-types安装后在 Claude Code 中输入/infrahub-converting-netbox-device-types确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
concepts.mdexamples.mdextending-your-schema.mdgenerators-module-ports.mdreference.mdrules/_sections.mdcoverage-report-unmapped.mdformat-template-objects.mdmapping-fallback-sources.mdmapping-profile-driven.mdmapping-shared-relationships.mdnaming-template-names.mdoutput-load-order.mdworkflow-schema-prerequisites.mdworkflow-use-the-bundled-scripts.mdscripts/materialize_module_ports.gqlmaterialize_module_ports.pynetbox_export_device_types.pynetbox_to_infrahub_templates.pyscripts/mappings/_template.ymlschema-library-module-ports.ymlschema-library-modules.ymlschema-library.yml详细介绍
NetBox 设备类型转换器
概述
将 NetBox 设备类型 YAML(netbox-community/devicetype-library 使用的格式,可在 NetBox Data Exchange 浏览)转换为 Infrahub 对象模板:可复用的蓝图,用于创建已预先配置好所有端口的设备。
转换由捆绑的 Python 脚本完成,无需手动操作。手动转换一台 48 端口交换机意味着要转录 48 个几乎相同的代码块,而该库包含数千种设备类型。脚本精准且可重复;本技能旨在帮助你将脚本指向正确的架构,并解读它提供的信息。
项目上下文
目标架构文件:
!find . -name "*.yml" -path "*schema*" 2>/dev/null | head -10
现有映射配置:
!find . -name "*.yml" -path "*mappings*" 2>/dev/null | head -10
使用场景
- 使用 NetBox 库中的厂商设备型号为新的 Infrahub 实例填充数据
- 为特定项目或实验室拓扑转换少量设备类型
- 在上游库或本地架构发生变化后重新运行转换
- 构建将 NetBox 字段绑定到自定义 Infrahub 架构的映射配置
不适用于让 NetBox 和 Infrahub 实时保持同步——这需要使用单独的产品 infrahub-sync。本技能用于转换已发布库中的设备类型定义,或从运行中的 NetBox 单次导出的设备类型定义。
转换的结构
一个 NetBox 文件会变成 三 个 Infrahub 工件, 因为 Infrahub 会拆分 NetBox 保持在一起的内容:
| NetBox | Infrahub | 原因 |
|---|---|---|
manufacturer: Cisco | OrganizationManufacturer 对象 | 制造商是一等对象 |
model、part_number、u_height、weight | DcimDeviceType 对象 | 模板不包含型号数据 |
interfaces: 和其他组件列表 | TemplateDcimDevice + 组件模板 | 可复用的蓝图 |
模板会关联到设备类型,因此根据模板创建设备时,也会一并关联其型号。
模块类型是第二类输入,包括线路卡、电源模块和收发器,位于同级的
module-types/ 目录中。它们没有 slug,转换器正是据此区分两类输入,因此可以一次性转换混合目录树。它们遵循相同的拆分方式(模块类型对象,以及可选的模块模板),并输出到 04_module_types.yml /
05_module_templates.yml。在对此作出任何承诺之前,请先阅读
extending-your-schema.md:模块端口只能转换到模块模板上,而 stock
schema-library 的 DcimModule 不会生成模块模板。使用 schema-library-modules.yml 时,这些端口会报告为已跳过;当 DcimModule 设置了 generate_template: true 后,schema-library-module-ports.yml 才会包含它们。
模块端口名称带有 NetBox 的 {module} 标记,任何转换都无法解析它——只有在安装模块后才能知道插槽位置。端口作为模块模板上的 DcimModulePort 声明导入后,捆绑的生成器会针对每个已安装的模块解析该标记,并根据接口端口创建实际的设备接口。控制台端口需要架构中包含控制台接口类型,而电源端口仍保持为声明。请参阅
generators-module-ports.md。
几乎所有意外情况都由以下三个事实造成——应当解释它们,而不是想当然:
Template*类型是生成的,而非手动编写的。 在节点上设置generate_template: true会创建这些类型; 如果未设置,它们就不存在。- 组件模板只来自
Component关系。Attribute关系仍指向实际对象。 - 型号数据位于设备类型上,而非模板上。 这就是为什么需要按此顺序使用三个文件。
如果你刚接触 Infrahub 的数据模型,或正要向他人讲解它,请参阅 concepts.md,其中对此有介绍,并附有 Infrahub 文档链接。
规则类别
| 优先级 | 类别 | 前缀 | 说明 |
|---|---|---|---|
| CRITICAL | 工作流 | workflow- | 必须先启用 generate_template;捆绑的脚本会完成相关工作 |
| CRITICAL | 映射 | mapping- | 名称来自架构,绝不猜测;冲突字段会声明优先级 |
| CRITICAL | 格式 | format- | 信封、Template<Kind>、嵌套组件 |
| HIGH | 命名 | naming- | 基于 slug、使用父级命名空间、保持唯一 |
| HIGH | 覆盖范围 | coverage- | 报告未转换的内容 |
| MEDIUM | 输出 | output- | 三个文件、加载顺序、分支优先 |
完整索引:rules/_sections.md。
工作流
1. 确认架构会生成模板
只有在节点声明了
generate_template: true 时,才会存在 Template* 类型。请检查目标架构,
不要想当然地认为该选项已启用或未启用——这是转换后什么也没有加载的最常见原因。
在 OpsMill schema-library 中,答案取决于版本:v2 及更高版本在
base/dcim.yml 中的 DcimDevice 上启用了该选项,而 v2 之前的版本中该行
被注释掉了。自定义架构通常需要自行添加。
请阅读 rules/workflow-schema-prerequisites.md。
如果未启用,请说明更改内容,不要悄悄修改:该标志会为每个 Component
关系生成 TemplateDcimDevice 和组件模板;这是增量添加,并且必须重新加载
架构,这些类型才会出现。启用该选项会修改用户的事实来源,因此应由用户决定——
展示单行差异,让他们自行选择。
2. 选择或编写映射配置文件
转换器通过配置文件将 NetBox 字段绑定到 Infrahub 属性,因此不会猜测名称。
- 使用 OpsMill schema-library?请从
scripts/mappings/schema-library.yml开始;如果还需要模块类型,请使用scripts/mappings/schema-library-modules.yml;如果还需要模块端口,请使用scripts/mappings/schema-library-module-ports.yml(参见 generators-module-ports.md)。 - 使用自定义架构?请将
scripts/mappings/_template.yml复制到工作目录(例如./mappings/my-schema.yml,切勿放在$SKILL中, 因为重新安装插件时该目录会被清空),然后逐个类型、逐个属性地阅读架构 YAML并填写配置。
请阅读
rules/mapping-profile-driven.md
和 reference.md,了解双方的完整字段清单。如果两个 NetBox 字段
争用同一个 Infrahub 属性——例如 description 与 comments,接口的 label 与
description——请用 fallback 声明优先级,而不是只选一个并丢弃另一个;参见
rules/mapping-fallback-sources.md。
在认定某项缺失之前,请先检查是否已有节点可以填补空缺。 控制台端口通常
建模为继承接口通用类型的节点;在这种情况下,它会沿用设备现有的 interfaces
关系,完全不需要修改架构——只需添加配置文件条目即可。如果两个列表共用一个关系,
请阅读
rules/mapping-shared-relationships.md:
弄错会悄无声息地丢弃较大的列表。
extending-your-schema.md
列出了 schema-library 和 infrahub-demo-dc 已提供的内容。
3. 获取输入
根据设备类型文件的位置,有两个来源。
从运行中的 NetBox 获取。 某个用户自己实例中的目录通常才是他们真正想导入的内容,而且它与已发布的库并不相同。scripts/netbox_export_device_types.py 通过 REST API 读取运行中的实例,并写入库文件格式:
pip install 'pynetbox>=7.0' pyyaml # NetBox's client, and the file writer
# SKILL is this skill's own directory, wherever it is installed
SKILL=/path/to/infrahub-converting-netbox-device-types
export NETBOX_TOKEN=...
python "$SKILL/scripts/netbox_export_device_types.py" \
--url https://netbox.example.com \
--in-use \
--module-types \
--output-dir ./netbox-export
请留在用户的工作目录中,并使用脚本的完整路径。 $SKILL 是此技能的安装位置;对于插件安装,它位于 ~/.claude/plugins/cache/ 下,而重新安装插件会清空该目录。从那里运行会将导出文件、克隆的库和生成的 YAML 都放在该目录中,下一次更新就会删除用户的数据。以下命令读取或写入的所有内容(./netbox-export、devicetype-library/、./generated)都相对于用户当前所在的位置。
--in-use 只保留至少关联一个设备的设备类型,以及至少关联一个模块的模块类型。在真实实例中,这比整个目录小得多,也更符合实际需求。
脚本会报告所有未能顺利转换的内容:NetBox 中存在但库格式无法承载的字段、NetBox 未设置但库格式要求的字段、该 NetBox 版本中不存在的端点、清理后发生冲突的文件名,以及版本早于 4.5 的 NetBox 所使用的前端口结构。转换前请阅读此列表,就像加载前阅读转换覆盖率报告一样。
这只是一次性快照导出到文件,并非同步。持续复制数据请使用单独的产品 infrahub-sync。
从已发布的库获取。 如果要为尚未收录的厂商型号建立初始数据,请克隆上游仓库,但要使用稀疏克隆。普通的 --depth 1 克隆会拉取 1.6 GB 数据,其中几乎全是转换器不会读取的机柜立面图。将范围限制为定义文件即可获取 11,500 多种设备类型和 2,000 多种模块类型,约占 60 MB:
git clone --depth 1 --filter=blob:none --sparse \
https://github.com/netbox-community/devicetype-library.git
git -C devicetype-library sparse-checkout set device-types module-types
如果只需要设备,请从该列表中移除 module-types。
转换器接受文件、目录(递归遍历)和 glob 模式。
4. 运行转换器
请运行转换器,不要自行重写。两个脚本都包含手写等效实现会悄然丢失的正确性保障,而且出错时看起来像成功:YAML 有效、没有错误、没有覆盖率报告,但数据有误。请阅读 rules/workflow-use-the-bundled-scripts.md。 如果某个架构不适用,应该使用映射配置文件,而不是换一个脚本。
python "$SKILL/scripts/netbox_to_infrahub_templates.py" \
devicetype-library/device-types/Cisco/ \
--mapping "$SKILL/scripts/mappings/schema-library.yml" \
--output-dir ./generated \
--report ./generated/coverage-report.md
对于实时导出的数据,请将其导出目录传给转换器。它会同时遍历 device-types/ 和 module-types/,因此需要能映射两者的配置文件:
python "$SKILL/scripts/netbox_to_infrahub_templates.py" \
./netbox-export/ \
--mapping "$SKILL/scripts/mappings/schema-library-modules.yml" \
--output-dir ./generated \
--report ./generated/coverage-report.md
退出码:0 表示已转换,1 表示配置文件无效或输入格式错误,2 表示未匹配到文件。
如果两个设备类型的 model 相同,转换器会拒绝处理并列出所有冲突对。模板使用设备类型的 model 来标识设备类型,因此同时加载两者会让其中一个覆盖另一个,而且不会报错;已发布的库中有少数此类冲突,涉及多个厂商。请勿将每组冲突中的两者都包含在输入中。
写入或手动编辑任何生成的文件前,请阅读
rules/format-template-objects.md
——其中的封装结构、Template<Kind> 划分,以及 {kind, data} 组件包装器,是确保输出可加载的关键——并阅读
rules/naming-template-names.md,因为除非使用所属父级为组件命名空间前缀,否则不同设备类型中的组件名称会发生冲突。
5. 阅读覆盖报告,解释缺失项并提供修复方案
对于典型的架构,每个 NetBox 文件中都有很大一部分无处可去。打开报告,并在 回复中:
- 指出缺失最多的内容——哪些组件列表 和哪些字段,以及对应数量。不要只说 存在一份报告。
- 解释架构为何无法容纳这些内容。
仅仅说“跳过了
console-ports”,对不了解组件模板 仅从Component关系生成的人来说,无法采取行动。请说明原因。 - 提供具体的修复方案。 被丢弃的字段只需添加一个 属性;被跳过的列表则需要添加一个节点,以及一对 Component/Parent。两者都属于增量修改。 extending-your-schema.md 提供了各个案例的可用 YAML,包括哪些 架构库扩展已涵盖其中一部分。
提出建议——不要擅自重写对方的架构。这是一次 针对其真实数据源的迁移。
请阅读 rules/coverage-report-unmapped.md。
适用时,值得点名指出的两个案例:
- 模块化机框——其端口位于模块
插槽中,因此有 414 种已发布设备类型(3.6%)声明了插槽但没有接口,
转换后会成为没有接口的模板。在架构库 v2
中,插槽本身也会转换(
TemplateDcimModuleBay), 这样空模板就能变得有用;schema-library-modules.yml配置 会映射它们。在 v2 之前的版本中,或在没有插槽节点的架构中, 它们仍会被报告为跳过。请参阅 extending-your-schema.md。 - 控制台端口通常只需更改配置,而不是架构——如果架构将其建模为
继承接口通用类型的节点,它们就已经通过
interfaces关系导入。
6. 加载到分支
infrahubctl branch create netbox-import
for file in generated/0*.yml; do
infrahubctl object load "$file" --branch netbox-import
done
加载顺序遵循依赖顺序——先制造商,再设备类型, 然后是模板。请阅读 rules/output-load-order.md。 切勿将批量导入直接加载到默认 分支。
扩展转换器
优先调整映射配置——它无需修改 Python,就能涵盖新的 类型、重命名的属性、额外的组件列表和条件值。只有遇到真正的新 机制(尚不存在的转换类型)时,才修改脚本。向脚本添加 特定于架构的特殊情况,会导致它无法再为其他人正常工作。
其测试位于
tests/scripts/test_netbox_to_infrahub_templates.py,
而模块端口生成器的测试位于
tests/scripts/test_materialize_module_ports.py。任何修改后都要运行
这些测试:
uv run invoke test
参考资料
| 文件 | 何时阅读 |
|---|---|
| concepts.md | 不熟悉 Infrahub 模型,或需要解释它时 |
| reference.md § 从正在运行的 NetBox 导出 | 设备类型位于正在运行的 NetBox 中:查看标志、身份验证,以及导出报告的内容 |
| extending-your-schema.md | 将报告中的缺失项转化为架构变更 |
| generators-module-ports.md | 模块端口作为声明导入,且需要将 {module} 标记解析为实际设备接口时 |
| reference.md | 查找 NetBox 字段或其对应的 Infrahub 字段 |
| examples.md | 需要转换、配置或架构补丁的完整示例时 |
| rules/ | 应用或检查特定规则 |
| ../infrahub-managing-objects/rules/value-profiles-templates.md | 手动编写模板,或选择配置还是模板时 |
| ../infrahub-managing-schemas/rules/relationship-component-parent.md | 添加生成模板所依据的组件关系时 |
Infrahub 文档
解释概念时请链接到这些页面——用户点击链接后学到的是相关功能,而不仅仅是这种转换。
| 主题 | 页面 |
|---|---|
| 对象模板是什么 | https://docs.infrahub.app/object-templates/overview |
| 启用和使用对象模板 | https://docs.infrahub.app/object-templates/use |
| 模板与 Profiles | https://docs.infrahub.app/object-templates/with-profiles |
| 每个对象的唯一值 | https://docs.infrahub.app/object-templates/allocate-resources-from-pools |
| 节点和属性 | https://docs.infrahub.app/schema/nodes-and-attributes |
| 关系(Component 与 Attribute) | https://docs.infrahub.app/schema/relationships |
| Generics 与继承 | https://docs.infrahub.app/schema/generics-and-inheritance |
| 在不派生 Schema 的情况下扩展它 | https://docs.infrahub.app/schema/extensions |
| 加载 Schema | https://docs.infrahub.app/schema/create-and-load |
| Schema 迁移及其风险 | https://docs.infrahub.app/schema/migration |
| Schema 属性参考 | https://docs.infrahub.app/reference/schema/node |
| Profiles 与模板的区别 | https://docs.infrahub.app/profiles/overview |
| 从头开始创建 Schema(教程) | https://docs.infrahub.app/academy/tutorials/build-your-first-schema |
生成器(安装后解析 {module}) | https://docs.infrahub.app/generators/overview |