Skip to content

transformqcow2 — VMware 虚拟机 → qcow2/libvirt 转换工具集

把 VMware 侧导出的虚拟机(.vmdk / .ova / OVF 目录 / .vmx / ESXi SSH / vCenter) 转成 qcow2 + libvirt XML,并按操作系统给出对应的驱动、引导、网络适配建议与检查清单。

支持的系统矩阵(本工具集的目标范围):

windows 2008/2012/2016/2019/2022
rhel   5/6/7/8/9
ubuntu 18.04/20.04/22.04/24.04/

对应入口脚本共 14 个(scripts/convert-*.sh),公共逻辑集中在 scripts/lib/common.sh


1. 目录结构与扩展点

transformqcow2/
├── readme.md                  # 本文档
└── scripts/
    ├── lib/common.sh          # 公共库:参数解析、环境探测、源识别、转换、
    │                          #         校验、libvirt XML 生成、日志/报告、汇总
    ├── selftest.sh            # 自检脚本(合成源 + 全矩阵 + 关键特性,可重复跑)
    ├── convert-rhel5.sh       # RHEL/CentOS 5(含 Rocky/Alma 同代)
    ├── convert-rhel6.sh … convert-rhel9.sh
    ├── convert-ubuntu-1804.sh … convert-ubuntu-2404.sh
    └── convert-windows-2008.sh … convert-windows-2022.sh

每个 convert-*.sh 只做三件事:声明系统画像(默认值)→ 实现系统相关钩子 → 调用公共流水线。 新增一个系统 = 复制一个入口脚本,改画像与钩子即可,不需要动公共库。

钩子(均可选,公共库提供默认空实现):

钩子用途
os_notes打印该系统转换前的注意事项清单
os_preflight_source源相关额外检查(驱动、固件、内核参数等)
os_prepare组装 CUSTOMIZE_ARGS(virt-customize)/ V2V_EXTRA_ARGS(virt-v2v)
os_manual_hintsimg 模式下的手工适配清单
os_post_convert转换/启动后的检查清单
os_parse_arg该系统专属参数(如 Windows 的 --win-x86--virtio-win-dir

画像变量(均可选,公共库有兜底默认值): MODE_DEFAULTFIRMWARE_DEFAULTDISK_BUS_DEFAULTNET_MODEL_DEFAULTMACHINE_TYPE_DEFAULTARCH_DEFAULTQCOW2_COMPAT_DEFAULTGUEST_FIX_DEFAULTBLOCK_DRIVER_DEFAULTVCPUS_DEFAULTMEM_MB_DEFAULTMEMSIZE_MB_DEFAULTALLOW_MODE_FALLBACKVIRTIO_WIN_DIR


2. 前置依赖

必需

依赖用途
bash ≥ 4.2脚本运行环境(关联数组、${x^^} 等)
qemu-img--mode img 转换、镜像信息/容量/校验和

按功能可选(缺失时脚本会明确告警并给出安装命令,不会静默降级)

依赖缺失时的影响
virt-v2v(+ libguestfs-toolslibvirt-daemon--mode v2v 不可用。Linux 脚本自动降级为 img 并告警;Windows 2012+ 直接报错退出(避免产出缺驱动、开机蓝屏的镜像);Windows 2008 因允许 ide/e1000 兜底才会降级
virt-customize / guestfish--guest-fix(客户机内重建 initramfs、改主机名、重置 root 密码、SELinux relabel)不可用;脚本改为打印手工适配命令清单
OVMF / edk2-ovmf无法生成 UEFI/Secure Boot 的 <loader>/<nvram>;脚本明确告警(Secure Boot 需要带 MS 密钥的 *.ms.fd
virtio-win(ISO 或目录)Windows 转换后缺 virtio 磁盘/网卡驱动;脚本告警并给出 --disk-bus sata --net-model e1000 兜底;指定 ISO 时会校验是否含对应系统目录(如 2k19
virsh--define/--autostart 不可用(XML 仍会生成,可手工导入)
fdisk / sfdisk无 libguestfs 时无法对裸盘源自动探测 ESP(UEFI)
isoinfo / 7z无法校验 virtio-win ISO 内容(只提示「无法判定」,不猜)
xmllint仅影响自检脚本对生成 XML 的合法性校验
tarlibarchive-tar-perlOVA 解包

Debian/Ubuntu 一次装齐(示例):

bash
apt install -y qemu-utils virt-v2v libguestfs-tools guestfsd supermin \
               ovmf virtio-win libvirt-daemon-system libxml2-utils dosfstools genisoimage

RHEL/Rocky/Alma:

bash
dnf install -y qemu-img virt-v2v libguestfs-tools-c edk2-ovmf virtio-win \
               libvirt libxml2 util-linux

环境变量

变量作用
VIRTIO_WIN / VIRTIO_WIN_ISO覆盖 virtio-win 自动探测路径(等价于 --virtio-win
VIRT_V2V_TMPDIR / TMPDIRvirt-v2v overlay 临时目录(建议 ≥ 源实际占用 + 1G)
LIBGUESTFS_BACKENDlibguestfs appliance 起不来时可试 direct
NO_COLOR置任意值关闭彩色输出(重定向到日志/CI 时有用)

3. 快速开始

bash
cd scripts

# 1) 本地 vmdk → qcow2 + libvirt XML(RHEL 8,默认走 virt-v2v)
./convert-rhel8.sh -s /data/export/rhel8-app01.vmdk -o /data/out -n rhel8-app01

# 2) 只做格式转换(不动客户机内部),并先预览命令、不落盘
./convert-ubuntu-2204.sh -s /data/export/u22.ova -o /data/out -n u22-web01 \
    --mode img --dry-run

# 3) Windows Server 2019(UEFI + Secure Boot,需要 virtio-win 与 OVMF *.ms.fd)
./convert-windows-2019.sh -s /data/export/w2019.ova -o /data/out -n w2019-db01 \
    --secure-boot --virtio-win /usr/share/virtio-win/virtio-win.iso

# 4) ESXi 上的 vmx 经 SSH 直接转换(不落本地全量拷贝)
./convert-rhel7.sh \
    -s 'ssh://root@10.0.0.11/vmfs/volumes/datastore1/rhel7/rhel7.vmx' \
    -o /data/out -n rhel7-app01 --password-file /root/.esxi-pass

# 5) vCenter 经 VDDK 拉取
./convert-rhel9.sh \
    -s 'vpx://root@10.0.0.10/DC01/esxi01?no_verify=1' --remote-guest rhel9-app01 \
    --transport vddk --vddk-libdir /opt/vmware-vix-disklib-distrib \
    --vddk-thumbprint 'AA:BB:CC:DD:EE:FF:...' --password-file /root/.vc-pass \
    -o /data/out -n rhel9-app01

# 6) 转换完成后直接注册到 libvirt 并设置自启
./convert-rhel8.sh -s /data/export/rhel8.vmdk -o /data/out -n rhel8-app01 \
    --define --autostart

任意脚本 -h 会打印「该系统示例 + 全部通用参数」。


4. 两种转换模式

--mode v2v(推荐)--mode img
工具virt-v2v-of qcow2qemu-img convert -O qcow2
客户机内部会改:注入 virtio 驱动、改引导、--firstboot 脚本、virt-customize 适配完全不改,只换磁盘格式
适用生产迁移,尤其 Windows已经预装 virtio/免驱设备、或只想要 qcow2 文件
风险依赖 libguestfs appliance 可用客户机内驱动/网络配置需人工处理,否则可能开不了机

各系统的 MODE_DEFAULT:除 RHEL 5 默认 img(内核无原生 virtio,v2v 收益低、风险高)外, 其余 13 个系统都默认 v2v

v2v 不可用时的降级策略(由各系统画像的 ALLOW_MODE_FALLBACK 决定):

  • 降级为 img 并告警:RHEL 6/7/8/9、Ubuntu 全部、Windows 2008(默认 sata/e1000 免驱兜底,降级后仍可开机);
  • 直接报错退出:Windows 2012 / 2016 / 2019 / 2022 —— 缺 virtio 驱动降级到 img 会产出 开机蓝屏(0x0000007B)的镜像,属于「静默产出坏结果」,必须显式处理。 确要降级请加 --allow-mode-fallback,并同时准备驱动方案 (客户机内预装 virtio-win,或用 --disk-bus sata --net-model e1000)。

5. 参数速查

位置参数:convert-xxx.sh <源> [<输出目录>](等价于 -s/-o)。

源与目标

参数说明
-s, --source <路径|URL>.vmdk / .ova / OVF 目录 / .vmx / 裸盘 / ssh:// / vpx://;源类型自动识别(无 --format 开关,识别不出会告警并按目录/远程/扩展名兜底)。.vmximg 模式会自动展开为它引用的 vmdk 再交给 qemu-imgqemu-img 不认识 .vmx,直接喂给它会被当 raw 读、产出几百字节的垃圾盘);展开不出本地磁盘时 ABORTED 退出并给对策,--mode v2v 则把 .vmx 原样交给 virt-v2v -i vmx
-o, --out, --out-dir <目录>输出目录,默认 ./out
-n, --name <虚拟机名>输出名,默认取源 basename
--remote-guest <名>远程源上的虚拟机名(ssh://vpx://
-it, --transport <vddk|nfc|ssh>远程输入传输方式
--vddk-libdir <目录> / --vddk-thumbprint <指纹> / --vddk-transports <列表>VDDK 传输所需
--password-file, -ip <文件>远程口令文件(建议 0600、无尾换行)
--remote-size <100G>远程源容量(用于空间估算)
--luks-key <selector>LUKS 解锁,如 all:key:PASS(对应 virt-v2v --key
-y, --yes免交互确认(脚本/批量场景)
--overwrite允许覆盖已存在的输出文件(默认拒绝)
--force-space空间估算不足时仍继续
--force-source跳过源合理性校验(见第 7 节)
--keep-work保留 OVA 解包等临时工作目录(默认清理)

转换与输出格式

参数说明
--mode <v2v|img>见第 4 节
--compressqcow2 压缩(qemu-img -c)。与 --prealloc 互斥:同用时告警并忽略 --prealloc
--cluster-size <64k|128k|…>qcow2 簇大小(Windows/大 IO 建议 128k
--compat <0.10|1.1>qcow2 版本;RHEL5 默认 0.10,其余 1.1
--prealloc <off|metadata|falloc|full>预分配方式
--checksum生成 <名称>.sha256
--no-check跳过转换后的 qemu-img check
--inspect校验阶段额外打印分区/文件系统视图
--compare校验阶段与源做逐块比对(慢)
--guest-fix / --no-guest-fix是否用 virt-customize 改客户机内部(默认按系统画像,当前全部为 off)
--selinux-relabelSELinux 全量 relabel(RHEL 系,需 --guest-fix
--hostname <名> / --root-password <口令>客户机内改造内容(需 --guest-fix

lazy_refcounts 无 CLI 开关:内部仅在 compat=1.1 时才可能启用,--compat 0.10 下会告警并强制关闭。

引导 / 设备 / 网络

参数说明
--firmware <bios|uefi>目标固件;未显式指定时才会尝试从源探测 ESP(见第 7 节)
--uefi / --bios--firmware 的快捷写法(显式指定后不再自动探测)
--secure-boot / --no-secure-bootSecure Boot(隐含 --uefi;XML 加 secure='yes'<smm>,需 OVMF_CODE*.ms.fd + OVMF_VARS.ms.fd
--disk-bus <virtio|scsi|sata|ide>磁盘总线(默认见第 9 节矩阵)
--block-driver <virtio-blk|virtio-scsi>仅 Windows + --mode v2v 生效
--net-model <virtio|e1000|e1000e|rtl8139>网卡型号
--libvirt-network <名>XML 用 libvirt NAT 网络(否则走桥接)
--bridge-name <名>桥名,默认 br0
--network-map <in:out>virt-v2v 网络映射,可多次(如 "VM Network:br0"
--net-style <bridge|network>上述映射写成 --bridge 还是 --network,默认 bridge
--mac-map <mac:…>virt-v2v --mac 精细映射,可多次
--mac <52:54:00:xx:xx:xx>在 libvirt XML 中固定 MAC(保留源 MAC);格式非法只告警并忽略,不写入 XML
--arch <x86_64|i686>客户机架构(仅这两种,其他值直接报错);--i386 / --32bit / --i686 是快捷写法,会额外告警:内存 > 3.5G 可能超 32 位上限、32 位 UEFI 需专门 OVMF(建议 --bios
--machine-type <q35|pc|…>libvirt XML 机型;默认 q35,RHEL5/6 与 Windows 2008 为 pc(不做取值校验,可写具体版本如 pc-i440fx-2.0
--vcpus <n> / --mem <MiB>XML 中的 vCPU/内存;未指定时用系统画像默认(见第 9 节,不从 OVF/vmx 读取
--memsize <MiB>仅 v2v:给转换 appliance 的内存
--virtio-win <iso|目录>覆盖 virtio-win 自动探测路径
--no-xml / --define / --autostart不生成 XML / 转换后 virsh define / 设置自启

观测

参数说明
--dry-run只预览将执行的命令与 XML,不落盘(见第 7 节)
--log <文件>自定义运行日志路径(默认 <输出目录>/logs/<名称>-<时间戳>.log
--report <文件>自定义报告 TSV 路径(默认 <输出目录>/convert-report.tsv
-h, --help打印「该系统示例 + 全部通用参数」

没有 --verbose/--quiet 开关:进度信息始终打印到终端并写入日志文件。 未知参数会直接报错退出(未知参数: xxx(用 -h 查看用法)),不会静默忽略; 系统专属参数由各脚本的 os_parse_arg 钩子消费。

Windows 专属:--win-x86(2008,切 i686 + 2k8 驱动目录)、--win-nonr2(2012,切 2k12)、 --virtio-win-dir <名>(覆盖驱动目录名)。


6. 输出物

一次成功转换后,输出目录内包含:

<outdir>/
├── <名称>.qcow2              # 转换结果
├── <名称>-disk2.qcow2 …      # 多盘源的第 2、3… 块盘
├── <名称>.libvirt.xml        # libvirt 域定义(--no-xml 可关闭)
├── <名称>.sha256             # --checksum 时生成
├── logs/
│   └── <名称>-<时间戳>.log    # 本次运行完整日志(含将执行/已执行的命令、环境快照、告警)
└── convert-report.tsv        # 一行一机的报告,便于批量归档

convert-report.tsv 列(Tab 分隔,含表头):

时间  系统  虚拟机  源  源类型  模式  虚拟容量  输出文件  输出大小  磁盘总线  固件  耗时(s)  状态

状态取值:SUCCESS / FAILED / ABORTED(rc=N) / SKIPPED即使中途报错退出也会写入一行, 方便批量转换后统计;异常时 qcow2 若已部分生成会被标记为 <未完成>

libvirt XML 要点(实际样例见 logs/ 同目录的 <名称>.libvirt.xml):

  • <domain type='kvm'><type arch='…' machine='…'>hvm</type><cpu mode='host-passthrough'>
  • <loader readonly='yes' type='pflash'> + <nvram template=…> 仅在固件为 UEFI 时写入; OVMF 按固定顺序探测:/usr/share/OVMF/OVMF_CODE.ms.fdOVMF_CODE.secboot.fdOVMF_CODE.fd/usr/share/edk2/ovmf/*/usr/share/qemu/OVMF.fd; 一个都没找到时写占位路径并告警(需手工修正);
  • --secure-boot<loader … secure='yes'> + <features> 里补 <smm state='on'/>。 若探测到的固件不是 *.ms.fd/*secboot*仍会写 secure='yes' 但告警 (缺 MS 密钥时 libvirt 会启动失败),需补装 ovmf/edk2-ovmf 或改用 --uefi
  • --arch i686 只影响 arch 属性与 <emulator>(优先 qemu-system-i386), 不会换成 32 位 OVMF —— 32 位客户机请配 --bios
  • <mac address='…'/> 仅在 --mac 通过格式校验时写入(非法只告警并忽略);
  • Windows 客户机额外写 <hyperv mode='custom'> 特性集、<clock offset='localtime'> + rtc/pit/hpet 计时器、<vmport state='off'/>;Linux 用 <clock offset='utc'>
  • 磁盘按 --disk-bus 生成 <target dev=…>virtiovda/vdbidehdasata/scsisda), 驱动统一 cache='none' io='native' discard='unmap'
  • 网络默认 <interface type='bridge'> + --bridge-name(默认 br0), 指定 --libvirt-network 则改为 <interface type='network'>

7. 安全与可预期行为

--dry-run(严格只读)

  • 只打印将要执行的命令与将要生成的 XML(预览到终端), 不创建输出目录、不写日志文件、不写 XML 文件、不写报告 TSV、不解包 OVA 到磁盘
  • 因此 dry-run 阶段无法读取 OVA/多盘目录内部的真实清单(日志里会说明);
  • XML 预览先写入 mktemp 临时文件再 cat 到当前 stdout(不写 /dev/stdout:stdout 被重定向到 普通文件时重开会以 O_TRUNC 清空之前打印的预检输出),预览文件随即删除; 「已生成 XML / virsh define」提示给的是正式运行时的落盘路径,不是那个临时文件;
  • 日志里会明确写出「未执行转换」「未产出文件,跳过完整性校验」「XML 仅预览未落盘」, 不会让人误以为已经转好了;
  • 空间检查在输出目录尚不存在时,会自动回退到最近的已存在父目录(避免因目录未创建而报错退出)。

源合理性校验(validate_source_sanity

对每个已识别的磁盘检查,任一失败即 ABORTED 退出(可用 --force-source 跳过):

检查拦截的问题
qemu-img info 能读到格式文件损坏、权限不足、不是磁盘镜像
扩展名与实际格式一致.vmdk 其实是 raw(qemu-img静默当 raw 转换,产出错误结果)
descriptor 型 VMDK 的 extent 文件齐全只拷了 .vmdk 描述符、漏了 -flat.vmdk / 分片
.vmx 引用的磁盘本地存在且可识别只拷了 .vmx、vmdk 仍在 datastore 上;.vmx 被当磁盘喂给 qemu-img
虚拟容量 ≥ 100MiB空文件、日志文件被误当磁盘
磁盘数量 ≥ 1目录里根本没有磁盘
输出虚拟容量 ≥ 源的一半源被误读(如把 .vmx/.ovf 当磁盘)导致产出垃圾盘

固件(BIOS/UEFI)探测

优先级:--firmware/--uefi/--secure-boot 显式指定 > 源探测 > 系统画像默认。

探测手段(按可靠性排序,只做能确证的判断):

  1. 元数据声明:.vmxfirmware = "efi"/"bios"、OVF/OVA 的 ovf:firmwareEFI/BIOS)—— 最可靠,且 --dry-run 下同样有效(OVA 不解包,只扫归档头部 64MiB 内的 OVF);
  2. libguestfs(guestfish)可用时:part-get-parttype + part-get-gpt-type 找 ESP (.vmx 源会先展开为其引用的 vmdk 再探测);
  3. 裸盘源(.raw/无扩展名/.img):fdisk -lEFI System,或 sfdisk 找分区类型 EF
  4. 分区表可读且确认没有 ESP → 固件明确判为 BIOS(不留「未知」);
  5. 既无元数据又读不到分区表(dry-run 下的 OVA/OVF 目录、ssh:///vpx:// 远程源)→ 暂不判定,日志写明原因与人工确认方法;这类源在转换完成后会按输出盘补判一次。

补充:

  • .vmxefi64.secureBoot.enabled = "TRUE" 而本次未开 --secure-boot → 告警提示 「源可能是 Secure Boot 引导,请加 --secure-boot」(不自动改固件,避免误判);
  • 判定结果与依据统一打印一行「依据「…」判定源为 … → …」,--firmware 显式指定时不再重复探测;
  • qcow2/VMDK 等镜像格式不会尝试直读分区表(会报错且结论不可靠); virt-fw-vars 只读 EFI 变量存储文件,不能用于源磁盘。

空间与覆盖保护

  • 转换前估算:输出 = 源实际占用 ×1.2 + 256M(--compress 时 ×0.7 + 256M); v2v 临时目录VIRT_V2V_TMPDIR/TMPDIR)≈ 实际占用 + 1G。 输出目录不足 → 直接退出;临时目录不足 → 告警并退出。确要继续加 --force-space
  • 远程源(ssh:///vpx://)无法估算容量时跳过空间检查并告警,可用 --remote-size 100G 指定;
  • 输出目录尚不存在时(例如 --dry-run),空间检查自动回退到最近的已存在祖先目录;
  • 输出文件已存在时拒绝执行,提示 --overwrite 或换 -n
  • --overwrite 会直接重转并覆盖同名文件(img 模式由 qemu-img 覆写;v2v 产物再重命名为 <名称>.qcow2 / <名称>-diskN.qcow2)。转换中途失败时残缺文件会留在原地, 但报告状态记为 FAILED/ABORTED(rc=N),不会被当成成功;重跑请先删除或继续 --overwrite

8. 自检脚本

scripts/selftest.sh合成源(稀疏 VMDK、descriptor+flat 两段式 VMDK、GPT+ESP 裸盘、 MBR 裸盘、OVA、多盘目录、垃圾镜像)覆盖全部脚本与关键特性,不需要真实 VMware 导出, 也不需要 libvirt/KVM;缺工具的用例自动 SKIP。

bash
cd scripts
./selftest.sh                  # 全量自检(mktemp 建临时目录,结束后自动清理)
./selftest.sh -q               # 快速模式:第 2 节矩阵只跑 rhel5/rhel9/ubuntu-2204/windows-2019,其余不变
./selftest.sh -k               # 保留临时工作目录,便于排查
./selftest.sh -w /tmp/st -k    # 指定工作目录(配合 -k 保留现场复现)
./selftest.sh -h               # 用法

退出码:0=全部通过(SKIP 不算失败)、1=有 FAIL(自动保留工作目录并列出失败用例)、 2=前置条件不满足(缺 qemu-imgmktemp 失败、未知参数)。

覆盖内容(12 节):

  1. bash -n 语法检查 + shellcheck -S error(如已安装)
  2. 全矩阵:14 个 convert-*.sh × --mode img,校验 qcow2 格式/容量、XML 合法性、汇总状态、报告 TSV、运行日志
  3. --dry-run 无副作用(含 OVA 源;XML 预览写临时文件再 cat,不污染重定向到文件时的预检输出)
  4. 覆盖保护 / --overwrite / --no-xml
  5. ESP 自动探测、MBR 明确判 BIOS、.vmx/OVA 元数据判固件(含 dry-run)、Secure Boot 元数据告警、--uefi--secure-boot(SMM + *.ms.fd)、--no-secure-boot
  6. --arch / --32bit / 默认 x86_64 / --machine-type
  7. 各系统默认值与降级策略(RHEL5 保守栈、RHEL6 降级、Windows 2008 免驱、Windows 2019 拒绝静默降级)
  8. 源类型覆盖:descriptor+flat VMDK、OVA(含解包与临时目录清理)、多盘目录(多 <disk> XML)、 本地 .vmx(展开为引用的 vmdk、跳过光驱与 present="FALSE"、引用盘缺失时 ABORTED)、 virt-v2v 命令构造(单元级:-i vmx/ova 必带源位置参数、-ic 连接串不重复)
  9. 源合理性校验与异常退出记录(含 --force-source
  10. 选项覆盖:--mac--bridge-name--libvirt-network--vcpus/--mem--checksum--compress/--prealloc 冲突、--cluster-size--compat 0.10--report/--log
  11. 客户机适配提示、手工清单、virtio-win 目录/ISO 校验(单元级)
  12. 全部脚本 -h 帮助完整性

9. 各系统默认值矩阵

固件默认全部为 bios;UEFI 通过源探测(OVF ovf:firmware / ESP)或 --uefi--secure-boot 指定。

系统模式磁盘总线网卡机型qcow2 compatvCPU / 内存(MiB)v2v memsize缺 virt-v2v 时
RHEL / CentOS 5imgidee1000pc0.102 / 20482048本就是 img
RHEL / CentOS 6v2vvirtiovirtiopc1.12 / 40963072降级 img + 告警
RHEL / CentOS 7v2vvirtiovirtioq351.12 / 40964096降级 img + 告警
RHEL / Rocky / Alma 8v2vvirtiovirtioq351.12 / 40964096降级 img + 告警
RHEL / Rocky / Alma 9v2vvirtiovirtioq351.12 / 40964096降级 img + 告警
Ubuntu 18.04v2vvirtiovirtioq351.12 / 40963072降级 img + 告警
Ubuntu 20.04v2vvirtiovirtioq351.12 / 40964096降级 img + 告警
Ubuntu 22.04v2vvirtiovirtioq351.12 / 40964096降级 img + 告警
Ubuntu 24.04v2vvirtiovirtioq351.12 / 40964096降级 img + 告警
Windows 2008 / 2008 R2v2vsatae1000pc1.12 / 40964096降级 img(免驱兜底)
Windows 2012 / 2012 R2v2vvirtiovirtioq351.12 / 40964096报错退出
Windows 2016v2vvirtiovirtioq351.14 / 81924096报错退出
Windows 2019v2vvirtiovirtioq351.14 / 81928192报错退出
Windows 2022v2vvirtiovirtioq351.14 / 81928192报错退出

Windows 的 virtio-win 驱动目录名(VIRTIO_WIN_DIR):2008→2k8R2、2012→2k12R2、 2016→2k16、2019→2k19、2022→2k22--win-x86(2008)切 2k8 + i686--win-nonr2(2012)切 2k12

各系统关键注意点(脚本运行时会打印对应清单,这里是要点摘录)

  • RHEL 5ide/e1000 免驱栈 + qcow2 compat 0.10;initramfs 里通常没有 virtio 驱动, 改 virtio 前必须在客户机内 mkinitrd/etc/modprobe.conf 里可能残留 alias eth0 pcnet32
  • RHEL 6:initramfs 需含 virtio_blk/virtio_scsi/virtio_pcidracut --force); 70-persistent-net.rules 会按旧 MAC 绑定网卡名,迁移后网卡可能变 eth1 导致无网络。
  • RHEL 7/8/9dracut --force + NetworkManager 连接按 MAC 绑定;SELinux 环境改动后建议 --selinux-relabel; RHEL 8/9 若源是 UEFI,需确认 grub2-efi-x64shimx64 已装。
  • Ubuntu 18.04+:netplan 的 match: macaddress 会让网卡改名后失联;update-initramfs -u; 云上镜像可能带 cloud-init,迁移后需清理 instance-id 或禁用数据源。
  • Windows:必须预装/注入 virtio-win(viostornetkvmballoonqxl); 转换后首次启动建议 bcdedit /set {current} bootstatuspolicy ignoreallfailures; 域控角色要记录 FSMO、核对时间同步(Kerberos 容忍 5 分钟); 激活方式(KMS/MAK)、静态路由、盘符布局要提前记录。

10. 故障排查

现象原因与处理
virt-v2v: command not found / 提示缺依赖virt-v2v + libguestfs-tools;Linux 会自动降级 img(有告警),Windows 2012+ 会退出
libguestfs appliance launch failed / supermin 报错guestfsd supermin linux-image-*;或 export LIBGUESTFS_BACKEND=direct;无 /dev/kvm 权限时把用户加入 kvm
Windows 转换后开机蓝屏 0x0000007B缺 virtio 磁盘驱动。用 --mode v2v --virtio-win <iso>;或临时 --disk-bus sata --net-model e1000 起来后再装驱动
UEFI 源转完起不来 / 进了 BIOS 引导菜单固件判定错了。用 --uefi 显式指定;确认 OVMF 已装;--arch i686 客户机不能用 64 位 OVMF_CODE.fd
Secure Boot 客户机报 secure='yes' 相关错误需要带 MS 密钥的 OVMF_CODE*.ms.fd;缺失时脚本会退回普通 UEFI 并告警,请补装 ovmf/edk2-ovmf
Linux 迁移后网卡名变了、拿不到 IP旧 MAC 绑定。改 netplan/ifcfg 的 MAC 匹配,或删 70-persistent-net.rules 后重建 initramfs;也可用 --mac 固定回旧 MAC
找不到系统盘 / initramfs panicinitramfs 无 virtio 驱动。dracut --force(RHEL)或 update-initramfs -u(Ubuntu);脚本会枚举客户机 /lib/modules 下的内核版本给出具体命令
.vmdk 转换结果异常(大小/内容不对)该文件其实是 raw,或 descriptor 的 extent 缺失。源合理性校验会拦下;确认无误再用 --force-source
.vmx 为源,产出的 qcow2 只有几百字节 / 起不来qemu-img 不认识 .vmx(会当 raw 读)。工具在 img 模式已自动展开为其引用的 vmdk,并在输出侧比对虚拟容量兜底;若展开不出本地磁盘会 ABORTED,按提示把 vmdk 下载到 vmx 同目录、或改 --mode v2v、或直接把 .vmdk/.ova 作为 -s
.vmx 展开失败:vmx 引用的磁盘在本地不存在vmdk 仍在 datastore 上(只拷了 vmx)。补齐 vmdk(或改 vmx 里的 fileName 为实际路径);远程可用 --mode v2v 让 virt-v2v 自己解析
输出目录空间不足预检按「源实际占用 × 1.5」拦截;换目录或清理后重跑
输出文件已存在被拒绝--overwrite(原子替换)或换 -n
OVA 解包失败tarlibarchive-tar-perl);OVA 内含 ovf + vmdk,也可先手工解包后用目录作为源
远程 ssh:// / vpx:// 连不上检查 --password-file--vddk-libdir--vddk-thumbprint;先用 --dry-run 看命令
想看将要执行什么但不落盘--dry-run(严格只读,连输出目录都不建)
日志/报告在哪输出目录内 run-<名称>-<时间戳>.logconvert-report.tsv;可用 --log/--report 指定路径

11. 已知限制

  • --dry-run 阶段无法读取 OVA/多盘目录内部真实清单(不落盘就不解包),因此该模式下的磁盘列表是保守估计;
  • --dry-run 下的固件判定依赖元数据(.vmxfirmware=、OVA 头部 OVF 的 ovf:firmware); 元数据里没有声明时不猜,日志写明「暂不判定」,转换完成后按输出盘补判;
  • OVA 的元数据扫描只读归档头部 64MiB(OVF 通常在最前),避免为找 firmware 声明而读完整个大文件;
  • ESP/UEFI 自动探测对 qcow2/VMDK 源在无 libguestfs 的机器上无法进行,会保持系统默认(日志有提示);
  • img 模式的 .vmx 源要求其引用的 vmdk 已在本地(工具不会去 datastore 拉取);
  • --guest-fix 依赖可用的 libguestfs appliance;失败时脚本会终止并记录 ABORTED,不会留下改坏一半的镜像;
  • 多盘源的主盘按 OVF/vmx 声明或文件名排序选取,特殊布局请核对日志中的磁盘清单;
  • 转换过程只读源,但 OVA 解包与 virt-v2v overlay 会占用临时空间(VIRT_V2V_TMPDIR/TMPDIR)。