查看: 52|回复: 0

一文讲透EVE-NG镜像识别的底层机制

433

主题

947

回帖

3266万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
32662992

推广达人宣传达人突出贡献优秀版主论坛元老

QQ

1 同样是qcow2,为什么有的能跑有的不能?一文讲透EVE-NG镜像识别的底层机制


1.1 现象引入

把一个qcow2文件扔进EVE-NG目录,重启服务——设备列表里没有它。换个目录名再试,出现了,但启动后黑屏。再改一下文件名,终于能跑。同样的文件,三个结果。

这不是玄学。EVE-NG识别镜像从来不是"有文件就行",背后是一套严格的链式校验:目录前缀匹配模板→磁盘文件名映射控制器→启动时创建差分盘→权限校验通过。任何一环断开,镜像要么不可见,要么启动失败。

这篇文章把这条链路拆干净。


1.2 概念拆解:三层识别机制

1.2.1 第一层:目录前缀匹配(门牌号)

快递送到楼栋,门牌号对不上就不送。EVE-NG的模板扫描逻辑同理。

镜像目录必须放在 /opt/unetlab/addons/qemu/ 下,且目录名格式严格为 {模板前缀}-{版本}。前缀必须与 /opt/unetlab/html/templates/intel/(或 amd/)下的YML模板文件名一致。

举个例子:

  • 模板文件 asav.yml → 镜像目录名必须以 asav- 开头,如 asav-9.20.1
  • 模板文件 fortinet-FGT.yml → 镜像目录名必须以 fortinet-FGT- 开头,如 fortinet-FGT-7.0.5

如果目录前缀与任何模板文件名不匹配,EVE-NG会根据 config.php 中的 TEMPLATE_DISABLED 常量决定行为:

  • .hided(默认):设备下拉列表中直接隐藏该模板
  • .missing:显示在列表中,但名称后追加 .missing 标记

源码层面,init.php:148-152 在页面加载时扫描 addon 目录,将匹配结果与模板名前缀比对,不匹配的直接标记为不可用。

注意:模板YML文件并不预设磁盘控制器类型——控制器完全由镜像目录中的磁盘文件名在运行时自动检测决定(见第二层)。

1.2.2 第二层:磁盘文件名→控制器映射(钥匙)

同一把锁,钥匙型号不对插不进去。磁盘文件名不是随便取的——它决定了QEMU用哪种控制器加载这块盘。

EVE-NG支持8种磁盘控制器格式,每种文件名前缀对应不同的QEMU启动参数:

磁盘文件名 控制器类型 典型设备
virtioa.qcow2 VirtIO(半虚拟化) 华为/思科/F5/Juniper等主流设备
hda.qcow2 IDE 旧型号设备(ACS、CheckPoint等)
scsia.qcow2 SCSI 部分存储类设备
sataa.qcow2 SATA VMware vCenter等
lsia.qcow2 LSI SCSI 部分老旧镜像
megasasa.qcow2 MegaSAS Cisco vWLC等
virtidea.qcow2 VirtIO-IDE Nokia Timos 19等
cdrom.iso CDROM Arista vEOS启动盘等

多盘场景下,文件名末尾字母按字母序递增:virtioa、virtiob、virtioc...

关键点:控制器类型由磁盘文件名自动检测(而非模板预设),用户在Web界面添加节点时不可更改。运行时 __node.php:990-1069 扫描镜像目录,通过正则匹配文件名前缀来决定QEMU启动参数——virtioa.qcow2 对应 -drive if=virtiohda.qcow2 对应 -hd[a](IDE),以此类推。如果镜像文件名与设备预期的控制器类型不匹配(例如设备需要VirtIO但文件名为 hda.qcow2),QEMU启动命令会传入错误的 -drive if=xxx-hd 参数,虚拟机内核无法识别启动盘——表现就是黑屏。

源码证据:__node.php:990-1069 通过正则匹配8种控制器前缀 + .qcow2$ 后缀来识别磁盘文件。

1.2.3 第三层:差分盘与权限(引擎点火)

模板是蓝图,差分盘是施工图,权限是施工许可证。三层缺一不可。

差分盘机制:当你在实验中启动一个QEMU节点时,EVE-NG不会直接读写模板镜像。而是通过 qemu-img create -b {模板路径}/virtioa.qcow2 -f qcow2 {运行路径}/virtioa.qcow2 创建一个Copy-On-Write(COW)叠加层。所有运行时变更写入差分盘,模板文件保持不变。

差分盘生成位置:/opt/unetlab/tmp/{tenant_id}/{lab_id}/{node_id}/virtioa.qcow2

这意味着:

  • 同一个模板镜像可以被多个节点同时使用,互不干扰
  • Wipe节点 = 删除差分盘,下次启动时重新从模板创建干净的叠加层
  • 差分盘损坏不影响模板,Wipe即可恢复

权限校验:上传镜像后必须执行 /opt/unetlab/wrappers/unl_wrapper -a fixpermissions 修复权限。这条命令不只是简单的chown——它按照EVE-NG内部的权限规范设置文件属主、属组和特殊权限位。手动执行 chown 会破坏特殊权限,导致QEMU无法读取磁盘文件,节点启动失败。

源码证据:cli.php:755-830prepareNode() 函数依次执行创建运行目录、复制skeleton、创建差分盘、创建TAP接口、桥接虚拟网络。整个流程无原子性保证——任何一步失败,已创建的差分盘、TAP接口、目录不会自动回滚,需手动清理或Wipe。


1.3 原理图解:镜像从上传到启动的完整链路

用户上传qcow2文件
    |
    v
放入 /opt/unetlab/addons/qemu/{前缀}-{版本}/
    |
    v
init.php 扫描:目录前缀 <--> YML模板文件名 匹配?
    |-- 不匹配 --> TEMPLATE_DISABLED 控制显示:
    |              .hided = 隐藏  /  .missing = 标记缺失
    |
    v 匹配
设备下拉列表显示该镜像,用户拖拽节点到画布
    |
    v 点击启动
apiStartLabNode()
    |
    v
unl_wrapper -a start
    |
    v
prepareNode() 执行:
  1. MkHomeDir()             --> 创建 /opt/unetlab/tmp/{tid}/{lid}/{nid}/
  2. cp -ar skeleton/*       --> 复制skeleton到jail/
  3. mount -B -o ro          --> 只读挂载jail和qemu目录
  4. qemu-img create -b ...  --> 从模板创建差分盘(已存在则跳过)
  5. addTap()                --> 创建TAP接口 vunl{t}_{id}_{if}
  6. connectInterface()      --> TAP接入bridge(vnet{t}_{net_id})
    |
    v
getCommand() 生成 QEMU 启动命令行:
  /opt/qemu/bin/qemu-system-x86_64
    -drive file=/opt/unetlab/tmp/.../virtioa.qcow2,if=virtio   <-- 控制器类型由文件名决定
    -m {RAM} -smp {CPU}
    -serial telnet:...:{console_port}
    ...
    |
    v
QEMU进程启动 --> 加载差分盘 --> 虚拟机识别磁盘 --> 启动OS

四个常见卡点

卡点 阶段 现象 根因
目录前缀不匹配 模板扫描 设备列表不可见 目录名前缀与YML模板文件名不一致
磁盘控制器选错 QEMU参数生成 启动后黑屏 文件名与设备预期控制器不匹配(如设备需VirtIO但文件名为hda.qcow2),QEMU传了错误的if=参数
权限未修复 磁盘加载 启动失败/报IO错误 未执行fixpermissions,QEMU无法读取磁盘
差分盘残留损坏 差分盘创建 启动异常/配置残留 之前prepareNode()失败未回滚,差分盘存在但损坏

1.4 实战案例:三个"同样qcow2"不同命运的真实场景

1.4.1 场景A:文件名对了,目录名错了

操作:假如把FortiGate镜像放进 /opt/unetlab/addons/qemu/fortigate-7.0.5/

结果:设备列表不显示。如果EVE-NG的模板文件名是 fortinet-FGT.yml,而目录前缀 fortigate- 与之不匹配,init.php扫描时直接跳过。

修正:

mv /opt/unetlab/addons/qemu/fortigate-7.0.5 /opt/unetlab/addons/qemu/fortinet-FGT-7.0.5

规律:不确定前缀时,去 /opt/unetlab/html/templates/intel/ 目录ls一下,YML文件名(去掉.yml)就是你要的前缀。

1.4.2 场景B:目录名对了,磁盘控制器选错了

操作:把华为AR1000v的qcow2文件命名为 hda.qcow2

结果:设备列表显示了,但启动后黑屏。因为华为AR1000v的设备内核期望VirtIO控制器,而文件名 hda.qcow2 使 __node.php 自动匹配为IDE控制器,QEMU按 -hd[a] 加载,华为VRP系统无法识别IDE盘。

修正:

mv /opt/unetlab/addons/qemu/huawei-AR1000v-5.170/hda.qcow2 /opt/unetlab/addons/qemu/huawei-AR1000v-5.170/virtioa.qcow2
/opt/unetlab/wrappers/unl_wrapper -a fixpermissions

规律:不确定该用哪种控制器时,参考官方Qemu image namings文档的映射表,确认设备内核期望的控制器类型后,用对应的文件名命名。或者自行尝试几个不同控制器类型,注意wipe后启动

1.4.3 场景C:一切正确,但忘了修权限

操作:通过SFTP上传完镜像,直接去Web界面添加节点

结果:节点启动失败,QEMU无法读写磁盘文件。

修正:

/opt/unetlab/wrappers/unl_wrapper -a fixpermissions

规律:每次上传镜像后,这条命令必须执行。不是可选项。而且绝对不能用 chown -R 替代——手动chown会破坏EVE-NG依赖的特殊权限位。


1.5 延伸思考

理解了三层识别机制,你就拥有了"不查教程也能自己造镜像"的能力。流程就四步:

  1. 对照 /opt/unetlab/html/templates/intel/ 找到对应模板,确认目录前缀
  2. 查官方Qemu image namings映射表,确认设备期望的磁盘控制器类型,用对应文件名命名(virtioa 还是 hda)
  3. 上传qcow2到正确目录,命名为正确的磁盘文件名
  4. 执行 fixpermissions

任何KVM镜像,只要宿主机CPU支持且资源足够,这套流程都能跑通。


本文为AI辅助生成草稿,技术细节请以实际环境验证为准。


1.6 内容来源

本文素材来自以下EVE-NG知识库文档,按章节索引:

1.6.1 现象引入

  • 镜像文件导入后无法使用?——EVE-NG亚太代理中文区独家合作伙伴:7项检查要点,印证"同样的文件不同结果"的常见现象

1.6.2 第一层:目录前缀匹配

  • 04.3 镜像管理.md 1.1节:目录命名规则 {前缀}-{版本};2.2节:模板文件名与镜像文件夹前缀的对应关系;3.2节:TEMPLATE_DISABLED机制(.hided/.missing)
  • 04.3 镜像管理.md R1校验记录:init.php:121-123 扫描 /opt/unetlab/addons/ 目录;init.php:148-152 模板名前缀匹配逻辑

1.6.3 第二层:磁盘文件名→控制器映射

  • Qemu image namings——EVE-NG官方文档:完整的前缀-厂商-磁盘文件名映射表,8种HDD格式说明
  • 04.3 镜像管理.md 1.3节:源码验证的8种磁盘控制器格式(含megasas和cdrom.iso,旧文档遗漏的2种已修正);Step 5陷阱扫描:扩展名错误(.qcow应为.qcow2)、缺失格式(megasas/cdrom.iso)
  • 03.3 节点与网络配置.md 3.1-3.2节:QEMU镜像目录命名前缀表、磁盘文件名与控制器对应表

1.6.4 第三层:差分盘与权限

  • T-STARTNODE 启动节点.md 维度5:prepareNode()完整流程(MkHomeDir→skeleton→mount→qemu-img create→addTap→connectInterface);差分盘路径映射;幂等性(已存在则跳过);无回滚机制
  • T-STARTNODE 启动节点.md 关键发现:差分盘"跳过已存在"特性、Wipe=删除差分盘、prepareNode失败残留不自动清理
  • EVE-NG制作镜像常用命令:fixpermissions命令、qemu-img commit提交、qemu-img convert压缩
  • 镜像文件导入后无法使用? 第5项:fixpermissions修复权限;第6项:节点资源配置

1.6.5 原理图解

  • T-STARTNODE 启动节点.md 维度5:从apiStartLabNode到QEMU进程启动的完整调用链(api→unl_wrapper→start()→prepareNode→getCommand→qemu_wrapper)
  • T-STARTNODE 启动节点.md 维度4:控制台端口计算公式、skeleton目录结构

1.6.6 实战案例

  • 镜像文件导入后无法使用? 第1项:扩展名检查(Dynamips=.image / IOL=.bin / QEMU=.qcow2);第2项:目录及文件名规范
  • Qemu image namings:fortinet-FGT前缀、huawei前缀、virtioa/hda映射关系
  • Huawei AR1000v 镜像导入教程:重命名为virtioa.qcow2 + fixpermissions的完整步骤

1.6.7 延伸思考

  • EVE-NG制作镜像常用命令:qemu-img create创建系统盘、qemu-img commit提交镜像、qemu-img convert -c压缩
  • 03.3 节点与网络配置.md 4.1-4.2节:镜像格式(QCOW2/RAW/VMDK)及转换命令
不忘初心
回复

使用道具 举报

本版积分规则

Copyright   ©2015-2026  EmulatedLab  Powered by Discuz!©   ( 浙ICP备2021010423号-1 )
快速回复 返回列表 返回顶部