Skip to content

<feature>[kvm]: ZSTAC-82672 add iothread vq capability#4025

Open
zstack-robot-2 wants to merge 1 commit into
feature-5.5.28-zbsfrom
sync/haidong.pang/feature/ZSTAC-82672-iothread-vq-mapping@@3
Open

<feature>[kvm]: ZSTAC-82672 add iothread vq capability#4025
zstack-robot-2 wants to merge 1 commit into
feature-5.5.28-zbsfrom
sync/haidong.pang/feature/ZSTAC-82672-iothread-vq-mapping@@3

Conversation

@zstack-robot-2
Copy link
Copy Markdown
Collaborator

Summary

Add the backend host capability foundation for IOThread VQ mapping. The capability is derived from qemu-kvm and libvirt package versions reported by KVM host facts.

Changes

  • Add capability::iothread-vq-mapping host SystemTag.
  • Add qemuKvmPackageVersion to HostFactResponse.
  • Derive and refresh the internal capability from qemu-kvm package version and libvirt package version.
  • Add focused Java tests for capability version comparison.

Testing

  • git diff --check
  • openspec validate --changes zbs-iothread-vq-mapping
  • Java unit test not run locally: mvn is unavailable on this host.

Resolves: ZSTAC-82672

sync from gitlab !9920

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Review Change Stack

Walkthrough

新增 HostFactResponse 中的 qemuKvmPackageVersion 字段与 IOTHREAD_VQ_MAPPING 系统标签常量,新增 KvmHostIothreadVqMappingCapability 进行版本判定,并在保存主机事实时依据判定创建或删除该标签,含单元测试覆盖。

sequenceDiagram
  participant saveKvmHost as saveKvmHostRelatedFacts
  participant refresh as refreshIothreadVqMappingCapability
  participant capability as KvmHostIothreadVqMappingCapability
  participant tag as KVMSystemTags.IOTHREAD_VQ_MAPPING
  saveKvmHost->>refresh: HostFactResponse (qemuKvmPackageVersion, libvirtPackageVersion)
  refresh->>capability: supported(qemuVersion, libvirtVersion)
  capability-->>refresh: boolean
  alt 版本满足
    refresh->>tag: 重建非固有标签
  else 版本不满足
    refresh->>tag: 删除标签
  end
Loading

🎯 2 (Simple) | ⏱️ ~12 分钟

变更说明

IO线程VQ映射能力检查

Layer / File(s) Summary
系统标签定义与主机数据模型
plugin/kvm/src/main/java/org/zstack/kvm/KVMSystemTags.java, plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java
定义 IOTHREAD_VQ_MAPPING 系统标签常量,在 HostFactResponse 中新增 qemuKvmPackageVersion 字段及其 getter/setter 方法。
主机版本能力检查类实现
plugin/kvm/src/main/java/org/zstack/kvm/KvmHostIothreadVqMappingCapability.java
实现版本检查逻辑:supported 方法判定 QEMU-KVM 与 libvirt 是否均满足最低版本要求,包含 versionAtLeastnormalizeVersion 辅助逻辑。
主机事实处理中的标签刷新集成
plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java
saveKvmHostRelatedFacts 流程中调用 refreshIothreadVqMappingCapability,根据能力检查结果重建或删除 IOTHREAD_VQ_MAPPING 标签。
版本能力检查的测试覆盖
test/src/test/java/org/zstack/kvm/KvmHostIothreadVqMappingCapabilityTest.java
新增 JUnit 测试类,包含 5 个用例,验证基准版本支持、不支持版本及缺失版本等场景。

总体描述

此 PR 为 KVM 主机添加了 IO 线程 VQ 映射能力的版本检查机制。在主机事实采集时,根据 QEMU-KVM 和 libvirt 包版本的支持情况,动态管理 capability::iothread-vq-mapping 系统标签的生命周期。

诗歌

🐰 版本之兔跳新园,
VQ映射入标签间;
QEMU与libvirt齐,
IO线程舞翩翩;
灰度上线心更安。

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 标题遵循要求的 [scope]: 格式,长度为54字符,不超过72字符限制,清楚描述了添加 iothread vq capability 的功能。
Description check ✅ Passed 描述与变更集相关,说明了添加 IOThread VQ 映射的后端主机能力基础、具体的代码变更内容、测试验证情况和关联任务追踪。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sync/haidong.pang/feature/ZSTAC-82672-iothread-vq-mapping@@3

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.42.2)
plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java

Comment @coderabbitai help to get the list of available commands and usage tips.

@MatheMatrix MatheMatrix force-pushed the sync/haidong.pang/feature/ZSTAC-82672-iothread-vq-mapping@@3 branch from 4e5a91e to a18fd36 Compare May 20, 2026 08:15
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
plugin/kvm/src/main/java/org/zstack/kvm/KvmHostIothreadVqMappingCapability.java (1)

27-38: ⚡ Quick win

建议为版本规范化逻辑添加注释说明。

normalizeVersion 方法的处理逻辑较为复杂,涉及空白符分割、按 - 拆段、过滤非数字开头段等操作。建议添加注释说明其设计意图,例如:

  • 为何取首个空白分隔的 token(处理可能包含多余空格或其他信息的版本字符串)
  • 为何过滤掉非数字开头的段(移除 "rc"、"beta" 等非版本号的限定符)
  • 边界情况处理(当所有段都被过滤后返回原始 trimmed 值)

这将有助于后续维护者理解代码意图,避免误改。

💡 建议的注释示例
 private static String normalizeVersion(String version) {
     if (StringUtils.isBlank(version)) {
         return null;
     }
 
+    // Extract first token and remove non-numeric prefixes (e.g., "rc", "beta", "el")
+    // to get a clean version string for comparison
     String trimmed = version.trim().split("\\s+")[0];
     String normalized = Arrays.stream(trimmed.split("-"))
             .filter(it -> !it.isEmpty())
             .filter(it -> Character.isDigit(it.charAt(0)))
             .collect(Collectors.joining("-"));
+    // If all segments are filtered out, fall back to original trimmed version
     return StringUtils.isBlank(normalized) ? trimmed : normalized;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@plugin/kvm/src/main/java/org/zstack/kvm/KvmHostIothreadVqMappingCapability.java`
around lines 27 - 38, Add explanatory JavaDoc and inline comments to the
normalizeVersion method: document that it first returns null for blank input,
then trims and takes the first whitespace-separated token to ignore trailing
metadata, explain splitting on '-' and filtering out empty segments and segments
that don't start with a digit (to remove qualifiers like "rc"/"beta"), and note
the fallback behavior that if all segments are filtered out it returns the
original trimmed token; reference the method name normalizeVersion and its
internal steps (trimmed token, split on "-", filter by Character.isDigit) so
future maintainers understand the intent and edge-case handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@plugin/kvm/src/main/java/org/zstack/kvm/KvmHostIothreadVqMappingCapability.java`:
- Around line 27-38: Add explanatory JavaDoc and inline comments to the
normalizeVersion method: document that it first returns null for blank input,
then trims and takes the first whitespace-separated token to ignore trailing
metadata, explain splitting on '-' and filtering out empty segments and segments
that don't start with a digit (to remove qualifiers like "rc"/"beta"), and note
the fallback behavior that if all segments are filtered out it returns the
original trimmed token; reference the method name normalizeVersion and its
internal steps (trimmed token, split on "-", filter by Character.isDigit) so
future maintainers understand the intent and edge-case handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: http://open.zstack.ai:20001/code-reviews/zstack-cloud.yaml (via .coderabbit.yaml)

Review profile: CHILL

Plan: Pro

Run ID: e61731a1-b927-4b2a-a268-6bc961019810

📥 Commits

Reviewing files that changed from the base of the PR and between 4e5a91e and a18fd36.

📒 Files selected for processing (5)
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMSystemTags.java
  • plugin/kvm/src/main/java/org/zstack/kvm/KvmHostIothreadVqMappingCapability.java
  • test/src/test/java/org/zstack/kvm/KvmHostIothreadVqMappingCapabilityTest.java

@MatheMatrix
Copy link
Copy Markdown
Owner

Comment from yaohua.wu:

Review: MR !9920 — ZSTAC-82672

关联 MR

  • zstack-utility !7104: agent 侧上报 qemuKvmPackageVersion(调用 linux.get_rpm_version("qemu-kvm") 填充)
  • premium !13981: 在 conf/grayUpgrade/grayUpgrade.json 注册新字段并设定起始灰度版本 5.5.28

整体评价

方案清晰:将 iothread-vq-mapping 能力检测下沉到 cloud 端,根据 KVM agent 上报的 qemu-kvm 与 libvirt 软件包版本动态创建/删除 SystemTag。抽出 KvmHostIothreadVqMappingCapability 工具类并附带 5 个单测,职责单一、可测试性好。@GrayVersion("5.5.28") 与 premium 侧的 grayUpgrade.json 注册值一致 ✓。

P1 — High

# File:Line Issue Fix
1 plugin/kvm/src/main/java/org/zstack/kvm/KvmHostIothreadVqMappingCapability.java:25-38 normalizeVersion/ComparableVersion 直接对含 git 短哈希 qualifier(如 g623f2a5caf)和 distro 后缀(.el8)的 RPM 版本字符串排序;Maven ComparableVersion 对未知 qualifier 走字典序,跨打包风格时行为不可预测 进入比较前显式截断到纯数字版本段:例如把 6.2.0-451.g623f2a5caf.el8 归一为 6.2.0-451,剔除 .g<hash>.el8 / .module+el8... 等 distro 后缀,再交给 ComparableVersion

触发场景:以 baseline 6.2.0-451.g623f2a5caf.el8 为最低要求,传入 6.2.0-451.module+el8.7.0+18516+a5e35adb(同 release 编号但用 module qualifier 风格)时,因 m > g,Maven ComparableVersion 会判为 ≥ baseline;反之同 release 编号但 .fc 之类前缀的版本会被字典序判为 < baseline。当前 5 个单测全部使用 g<hash>.el8 一种格式,缺少跨打包格式回归保护。

P2 — Moderate

# File:Line Issue Fix
1 plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java:6339 refreshIothreadVqMappingCapability(ret) 与紧跟其后 VIRTIO_SCSI 的能力检测放在同一段,但形态不一致:VIRTIO_SCSI 走 inline if + recreateNonInherentTag,新能力走独立私有方法 形式上不算错,但 maintainer 一致性考虑,可考虑统一抽成一个 refreshHostCapabilityTags(ret) 入口集中处理 capability 类 tag 的刷新;当前作为 P2 不阻塞合入
2 plugin/kvm/src/main/java/org/zstack/kvm/KVMSystemTags.java:46 新 tag capability::iothread-vq-mapping 紧跟 legacy VIRTIO_SCSI = "capability:virtio-scsi"(单冒号),两行视觉上易混;同文件下方 VOLUME_VIRTIO_SCSI = "capability::virtio-scsi" 走双冒号是标准约定 建议把 IOTHREAD_VQ_MAPPING 移到 VOLUME_VIRTIO_SCSI 附近聚类管理 host-capability 类 tag,并对 legacy VIRTIO_SCSI 的单冒号写法加一行注释说明历史原因

P3 — Low / 优点

  • 抽出独立工具类 KvmHostIothreadVqMappingCapability + 5 case 单测(baseline / 不足 / null / empty),符合 ZStack 内部"扩展点应可独立测试"的代码评审惯例
  • 能力不满足时显式 KVMSystemTags.IOTHREAD_VQ_MAPPING.delete(self.getUuid()),保证 host 降级 qemu-kvm 包后 tag 状态能反向收敛,避免遗留脏 tag

Coverage

  • 单测仅 supported() 路径,未覆盖 refreshIothreadVqMappingCapability 端到端;建议在 KVMHost*Test 加一个 fact-driven 验证(mock fact 返回不同版本组合,断言 tag 出现/删除)
  • 关联子任务 ZSTAC-85140("开启了多 iothread 的 zbs 盘迁移到 zstone 会带来性能降级")仍处于 Open。本 MR 只构建了能力开关,业务方在依赖该 tag 启用 iothread 前需先确认该性能子任务的应对方案

Verdict

APPROVED with comments — P1 为加固建议而非阻塞;版本比较在已验证的 RHEL g-hash 包格式下能正常工作,但跨打包格式风险建议在合入前评估。


🤖 Robot Reviewer

Resolves: ZSTAC-82672

Change-Id: I4c48ef8c9d16eac758ccefcb03fbd33c4c412bfe
@MatheMatrix MatheMatrix force-pushed the sync/haidong.pang/feature/ZSTAC-82672-iothread-vq-mapping@@3 branch from a18fd36 to 5949dd4 Compare May 20, 2026 08:38
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/src/test/java/org/zstack/kvm/KvmHostIothreadVqMappingCapabilityTest.java (1)

10-14: ⚡ Quick win

建议补一条“跨打包风格排序”回归用例,锁定比较语义。

当前正向用例已覆盖多种格式,但还缺少“不同 qualifier 风格混用时,数值发布号优先”的断言(例如 .g<hash>.el8 vs .module+el8... 的边界比较)。这条用例能直接防回归到词典序误判。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@test/src/test/java/org/zstack/kvm/KvmHostIothreadVqMappingCapabilityTest.java`
around lines 10 - 14, Add a regression test in supportsBaselineVersions that
covers "mixed packaging qualifier" ordering to lock the comparison semantics:
call KvmHostIothreadVqMappingCapability.supported with two versions that are
identical up to the numeric release but differ in qualifier style (e.g. one with
.g<hash>.el8 and the other with .module+el8...) and assert the result matches
numeric-release precedence (the expected boolean). Place this new assert
alongside the existing asserts in supportsBaselineVersions so it catches
regressions from lexicographic ordering mistakes in
KvmHostIothreadVqMappingCapability.supported.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@test/src/test/java/org/zstack/kvm/KvmHostIothreadVqMappingCapabilityTest.java`:
- Around line 10-14: Add a regression test in supportsBaselineVersions that
covers "mixed packaging qualifier" ordering to lock the comparison semantics:
call KvmHostIothreadVqMappingCapability.supported with two versions that are
identical up to the numeric release but differ in qualifier style (e.g. one with
.g<hash>.el8 and the other with .module+el8...) and assert the result matches
numeric-release precedence (the expected boolean). Place this new assert
alongside the existing asserts in supportsBaselineVersions so it catches
regressions from lexicographic ordering mistakes in
KvmHostIothreadVqMappingCapability.supported.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: http://open.zstack.ai:20001/code-reviews/zstack-cloud.yaml (via .coderabbit.yaml)

Review profile: CHILL

Plan: Pro

Run ID: 11dc98af-87f8-45b0-bb02-b9123499995e

📥 Commits

Reviewing files that changed from the base of the PR and between a18fd36 and 5949dd4.

📒 Files selected for processing (5)
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMSystemTags.java
  • plugin/kvm/src/main/java/org/zstack/kvm/KvmHostIothreadVqMappingCapability.java
  • test/src/test/java/org/zstack/kvm/KvmHostIothreadVqMappingCapabilityTest.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants