Skip to content

<fix>[vm]: filter zbs for encrypted auto ps#4464

Open
zstack-robot-2 wants to merge 1 commit into
feature-zsv-5.1.0-encryptionfrom
sync/zstackio/codex/filter-zhps-encrypted-auto-ps
Open

<fix>[vm]: filter zbs for encrypted auto ps#4464
zstack-robot-2 wants to merge 1 commit into
feature-zsv-5.1.0-encryptionfrom
sync/zstackio/codex/filter-zhps-encrypted-auto-ps

Conversation

@zstack-robot-2

Copy link
Copy Markdown
Collaborator

Summary

Filter ZBS primary storage from encrypted VM disk automatic primary storage allocation.

Changes

  • Add VmAllocatePrimaryStorageExtensionPoint and centralize encrypted auto-PS filtering in EncryptedVolumePrimaryStorageAllocatorExtension.
  • Call the extension from VM creation allocation paths, including host+PS allocation, root/data allocation, other-disk instantiation, and template data volume instantiation.
  • Add a unit test for the extension entry behavior.

Testing

  • git diff --cached --check
  • cbok zsv compile --no-deploy was attempted, but the remote Docker host failed before Java compile with No space left on device.

sync from gitlab !10426

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 13 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 05d66373-a706-4cde-befc-d2a99f52ffd1

📥 Commits

Reviewing files that changed from the base of the PR and between 1c435db and 92b7973.

⛔ Files ignored due to path filters (1)
  • conf/springConfigXml/VolumeManager.xml is excluded by !**/*.xml
📒 Files selected for processing (15)
  • compute/src/main/java/org/zstack/compute/vm/VmAllocateHostAndPrimaryStorageFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmInstantiateOtherDiskFlow.java
  • header/src/main/java/org/zstack/header/storage/primary/AllocatePrimaryStorageMsg.java
  • header/src/main/java/org/zstack/header/storage/primary/PrimaryStorageFeature.java
  • header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java
  • storage/src/main/java/org/zstack/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtension.java
  • storage/src/main/java/org/zstack/storage/encrypt/VolumeSourceEncryptionResolver.java
  • storage/src/main/java/org/zstack/storage/primary/PrimaryStorageFeatureAllocatorExtensionPoint.java
  • storage/src/main/java/org/zstack/storage/volume/InstantiateVolumeForNewCreatedVmExtension.java
  • storage/src/main/java/org/zstack/storage/volume/VolumeApiInterceptor.java
  • storage/src/main/java/org/zstack/storage/volume/VolumeBase.java
  • storage/src/main/java/org/zstack/storage/volume/VolumeManagerImpl.java
  • test/src/test/groovy/org/zstack/test/integration/storage/primary/EncryptedVolumePrimaryStorageAllocationCase.groovy

Walkthrough

新增 ENCRYPTED_VOLUME 主存储特性及候选过滤扩展点,使加密卷在多个分配流程中携带特性,并过滤不支持加密卷的外部主存储;新增无候选失败处理和集成测试。

Changes

加密卷主存储分配

Layer / File(s) Summary
加密卷特性与扩展点契约
header/src/main/java/org/zstack/header/storage/primary/..., header/src/main/java/org/zstack/header/vm/...
新增 ENCRYPTED_VOLUME 枚举、特性追加方法和虚拟机主存储候选过滤扩展点。
分配流程传递加密卷特性
compute/src/main/java/org/zstack/compute/vm/..., storage/src/main/java/org/zstack/storage/volume/...
多个卷分配流程在加密且未指定主存储时追加加密卷特性;加密模板数据盘不再回退到默认主存储。
虚拟机候选过滤接入
compute/src/main/java/org/zstack/compute/vm/VmAllocateHostAndPrimaryStorageFlow.java
在生成主存储组合前调用扩展点过滤 root/data 候选,无候选组合时直接失败。
外部主存储加密过滤
storage/src/main/java/org/zstack/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtension.java
查询 expon/vhost 外部主存储并从加密卷候选中移除。
集成验证
test/src/test/groovy/org/zstack/test/integration/storage/primary/EncryptedVolumePrimaryStorageAllocationCase.groovy
验证普通卷可分配外部主存储,而加密卷特性分配返回无候选错误。

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Flow as VM allocation flow
  participant Allocator as EncryptedVolumePrimaryStorageAllocatorExtension
  participant StorageDB as ExternalPrimaryStorageVO
  participant CloudBus

  Flow->>Allocator: 过滤 root/data 主存储候选
  Allocator->>StorageDB: 查询不支持加密卷的外部主存储
  StorageDB-->>Allocator: 返回主存储 UUID
  Allocator-->>Flow: 返回过滤后的候选
  Flow->>CloudBus: 发送主存储分配请求
  CloudBus-->>Flow: 返回成功或无候选失败
Loading

Suggested reviewers: taogan21

Poem

我是小兔,蹦过存储田,
加密标签亮闪闪。
不合适的主存储请走远,
候选清空即报错,
测试萝卜香满园。

🚥 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 标题简洁且准确概括了本次对加密自动主存分配过滤 ZBS 的主要变更。
Description check ✅ Passed 描述与该变更集一致,准确说明了加密卷自动主存过滤、接入点扩展和测试情况。
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sync/zstackio/codex/filter-zhps-encrypted-auto-ps

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (5)
test/src/test/java/org/zstack/test/unittest/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtensionTest.java (1)

15-36: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议补充 filterPrimaryStorageCandidatesshouldAllocatePrimaryStorageForTemplateDataVolume 的用例。

当前仅覆盖 beforeAllocatePrimaryStorage。另外两个 override 方法涉及 DB 查询分支与短路逻辑,是本次过滤行为的核心路径,建议补充测试(可考虑 mock Q)以覆盖候选过滤与模板数据卷分配判定。

🤖 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/test/unittest/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtensionTest.java`
around lines 15 - 36, Current tests only cover beforeAllocatePrimaryStorage, but
the core filtering logic also lives in filterPrimaryStorageCandidates and
shouldAllocatePrimaryStorageForTemplateDataVolume. Add test cases for these two
methods in EncryptedVolumePrimaryStorageAllocatorExtensionTest, including the
DB-query branch in filterPrimaryStorageCandidates and the short-circuit behavior
in shouldAllocatePrimaryStorageForTemplateDataVolume; use mocking for Q where
needed so both candidate filtering and template data volume allocation decisions
are verified.
compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java (1)

258-264: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

扩展点调用循环在多个 Flow 中重复。

相同的 pluginRgty.getExtensionList(VmAllocatePrimaryStorageExtensionPoint.class) 遍历回调逻辑在 VmAllocatePrimaryStorageFlowVmInstantiateOtherDiskFlowbeforeAllocatePrimaryStorage)以及 VmAllocateHostAndPrimaryStorageFlowfilterPrimaryStorageCandidates)中重复出现。可考虑参照 ZStack 既有的 *ExtensionPointEmitter 模式抽出统一的 emitter,减少重复并集中管理契约。

🤖 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
`@compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java`
around lines 258 - 264, The extension-point iteration logic for
VmAllocatePrimaryStorageExtensionPoint is duplicated across multiple flows, so
extract it into a shared emitter following the existing *ExtensionPointEmitter
pattern. Create a centralized emitter for the
pluginRgty.getExtensionList(VmAllocatePrimaryStorageExtensionPoint.class)
callback sequence and use it from
VmAllocatePrimaryStorageFlow.beforeAllocatePrimaryStorage,
VmInstantiateOtherDiskFlow.beforeAllocatePrimaryStorage, and
VmAllocateHostAndPrimaryStorageFlow.filterPrimaryStorageCandidates to keep the
contract in one place and remove repeated loops.
header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java (1)

8-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

建议在扩展点接口上明确 spec/disk 的可空契约。

当前多个调用方会传入 null:VmInstantiateOtherDiskFlow 传入 spec=null,而 VmAllocatePrimaryStorageFlow/VmAllocateHostAndPrimaryStorageFlow 在自动分配分支可能传入 disk=nullgetRootDisk() 可能为 null)。默认实现不解引用这些参数因而安全,但后续新增的实现容易在未察觉的情况下触发 NPE。建议在 Javadoc 中说明各参数何时可能为 null,提示实现方做空值防护。

🤖 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
`@header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java`
around lines 8 - 18, Clarify the nullable contract for the
VmAllocatePrimaryStorageExtensionPoint methods so implementers know that spec
and disk may be null in some call paths. Update the interface Javadoc around
beforeAllocatePrimaryStorage, filterPrimaryStorageCandidates, and
shouldAllocatePrimaryStorageForTemplateDataVolume to state when VmInstanceSpec
or DiskAO can be absent, referencing the extension point methods directly so
future implementations add null checks and avoid NPEs.
storage/src/main/java/org/zstack/storage/volume/InstantiateVolumeForNewCreatedVmExtension.java (2)

307-315: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

可用 Stream anyMatch 替代显式循环。

该判断逻辑适合用 Stream 表达。As per coding guidelines:“使用 Java Stream 或 Lambda 表达式代替冗长的循环与条件判断”。

♻️ 建议的写法
-    private boolean shouldAllocatePrimaryStorageForTemplateDataVolume(VmInstanceSpec spec, DiskAO diskAO, String defaultPsUuid) {
-        for (VmAllocatePrimaryStorageExtensionPoint ext :
-                pluginRgty.getExtensionList(VmAllocatePrimaryStorageExtensionPoint.class)) {
-            if (ext.shouldAllocatePrimaryStorageForTemplateDataVolume(spec, diskAO, defaultPsUuid)) {
-                return true;
-            }
-        }
-        return false;
-    }
+    private boolean shouldAllocatePrimaryStorageForTemplateDataVolume(VmInstanceSpec spec, DiskAO diskAO, String defaultPsUuid) {
+        return pluginRgty.getExtensionList(VmAllocatePrimaryStorageExtensionPoint.class).stream()
+                .anyMatch(ext -> ext.shouldAllocatePrimaryStorageForTemplateDataVolume(spec, diskAO, defaultPsUuid));
+    }
🤖 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
`@storage/src/main/java/org/zstack/storage/volume/InstantiateVolumeForNewCreatedVmExtension.java`
around lines 307 - 315, Replace the explicit loop in
shouldAllocatePrimaryStorageForTemplateDataVolume with a Stream anyMatch chain
over pluginRgty.getExtensionList(VmAllocatePrimaryStorageExtensionPoint.class),
using the same predicate
ext.shouldAllocatePrimaryStorageForTemplateDataVolume(spec, diskAO,
defaultPsUuid) to preserve behavior while following the Stream/Lambda guideline.

Source: Path instructions


276-278: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议简化嵌套三元表达式以提升可读性。

psUuid 使用了嵌套三元,语义不直观。可改用早返回或普通条件赋值表达清楚意图。As per coding guidelines:“if 条件表达不宜过长或过于复杂,必要时可以将条件抽成 boolean 变量描述”,并尽量减少难以阅读的分支结构。

♻️ 建议的写法
-                boolean allocatePrimaryStorage = shouldAllocatePrimaryStorageForTemplateDataVolume(spec, diskAO, defaultPsUuid);
-                String psUuid = diskAO.getPrimaryStorageUuid() != null ? diskAO.getPrimaryStorageUuid() :
-                        allocatePrimaryStorage ? null : defaultPsUuid;
+                boolean allocatePrimaryStorage = shouldAllocatePrimaryStorageForTemplateDataVolume(spec, diskAO, defaultPsUuid);
+                String psUuid;
+                if (diskAO.getPrimaryStorageUuid() != null) {
+                    psUuid = diskAO.getPrimaryStorageUuid();
+                } else {
+                    psUuid = allocatePrimaryStorage ? null : defaultPsUuid;
+                }
🤖 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
`@storage/src/main/java/org/zstack/storage/volume/InstantiateVolumeForNewCreatedVmExtension.java`
around lines 276 - 278, The psUuid assignment in
InstantiateVolumeForNewCreatedVmExtension uses a nested ternary that is hard to
read; replace it with clearer conditional logic, such as an explicit if/else or
early-return style, while preserving the same behavior based on
diskAO.getPrimaryStorageUuid(), allocatePrimaryStorage, and defaultPsUuid. Keep
the boolean from shouldAllocatePrimaryStorageForTemplateDataVolume() as the
descriptive condition and use it to make the storage selection flow obvious.

Source: Path instructions

🤖 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
`@compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java`:
- Around line 258-264: The extension-point iteration logic for
VmAllocatePrimaryStorageExtensionPoint is duplicated across multiple flows, so
extract it into a shared emitter following the existing *ExtensionPointEmitter
pattern. Create a centralized emitter for the
pluginRgty.getExtensionList(VmAllocatePrimaryStorageExtensionPoint.class)
callback sequence and use it from
VmAllocatePrimaryStorageFlow.beforeAllocatePrimaryStorage,
VmInstantiateOtherDiskFlow.beforeAllocatePrimaryStorage, and
VmAllocateHostAndPrimaryStorageFlow.filterPrimaryStorageCandidates to keep the
contract in one place and remove repeated loops.

In
`@header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java`:
- Around line 8-18: Clarify the nullable contract for the
VmAllocatePrimaryStorageExtensionPoint methods so implementers know that spec
and disk may be null in some call paths. Update the interface Javadoc around
beforeAllocatePrimaryStorage, filterPrimaryStorageCandidates, and
shouldAllocatePrimaryStorageForTemplateDataVolume to state when VmInstanceSpec
or DiskAO can be absent, referencing the extension point methods directly so
future implementations add null checks and avoid NPEs.

In
`@storage/src/main/java/org/zstack/storage/volume/InstantiateVolumeForNewCreatedVmExtension.java`:
- Around line 307-315: Replace the explicit loop in
shouldAllocatePrimaryStorageForTemplateDataVolume with a Stream anyMatch chain
over pluginRgty.getExtensionList(VmAllocatePrimaryStorageExtensionPoint.class),
using the same predicate
ext.shouldAllocatePrimaryStorageForTemplateDataVolume(spec, diskAO,
defaultPsUuid) to preserve behavior while following the Stream/Lambda guideline.
- Around line 276-278: The psUuid assignment in
InstantiateVolumeForNewCreatedVmExtension uses a nested ternary that is hard to
read; replace it with clearer conditional logic, such as an explicit if/else or
early-return style, while preserving the same behavior based on
diskAO.getPrimaryStorageUuid(), allocatePrimaryStorage, and defaultPsUuid. Keep
the boolean from shouldAllocatePrimaryStorageForTemplateDataVolume() as the
descriptive condition and use it to make the storage selection flow obvious.

In
`@test/src/test/java/org/zstack/test/unittest/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtensionTest.java`:
- Around line 15-36: Current tests only cover beforeAllocatePrimaryStorage, but
the core filtering logic also lives in filterPrimaryStorageCandidates and
shouldAllocatePrimaryStorageForTemplateDataVolume. Add test cases for these two
methods in EncryptedVolumePrimaryStorageAllocatorExtensionTest, including the
DB-query branch in filterPrimaryStorageCandidates and the short-circuit behavior
in shouldAllocatePrimaryStorageForTemplateDataVolume; use mocking for Q where
needed so both candidate filtering and template data volume allocation decisions
are verified.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ecc85355-2f22-4d1d-8987-4cf43115be05

📥 Commits

Reviewing files that changed from the base of the PR and between 45e799e and cb00422.

⛔ Files ignored due to path filters (1)
  • conf/springConfigXml/VolumeManager.xml is excluded by !**/*.xml
📒 Files selected for processing (7)
  • compute/src/main/java/org/zstack/compute/vm/VmAllocateHostAndPrimaryStorageFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmInstantiateOtherDiskFlow.java
  • header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java
  • storage/src/main/java/org/zstack/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtension.java
  • storage/src/main/java/org/zstack/storage/volume/InstantiateVolumeForNewCreatedVmExtension.java
  • test/src/test/java/org/zstack/test/unittest/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtensionTest.java

@MatheMatrix MatheMatrix force-pushed the sync/zstackio/codex/filter-zhps-encrypted-auto-ps branch 7 times, most recently from 29fed71 to 478e59b Compare July 7, 2026 14:00
@MatheMatrix

Copy link
Copy Markdown
Owner

Comment from yaohua.wu:

Review: MR !10426 — ZSV-12607

Background (preserved across rounds)

  • Jira: ZSV-12607 — 【硬盘加密】硬盘使用数据存储未zhps时 禁止开启硬盘加密
  • Bug summary: ZHPS 后端不支持加密硬盘,Jira 评论要求创建 VM / 新增硬盘时,硬盘存储位置为“自动选择”且开启加密时不能调度到 ZHPS;同时提到迁移更改数据存储、主机+数据存储时也不能选择 ZHPS。
  • Intent & scope: 本 MR 新增 encryptedVolumeAutoAllocation 标志,将其从 VM 磁盘自动分配路径传到 primary storage allocator,并通过 EncryptedVolumePrimaryStorageAllocatorExtension 过滤 identity=expon、protocol=Vhost 的 ZHPS 候选。
  • Round 1 initial findings: 2 × Critical,集中在模板数据盘创建与挂载未实例化加密云盘的自动主存储分配路径。
  • Suggested fix direction: 把“加密 + 自动选择主存储”的语义贯穿所有会创建 AllocatePrimaryStorage(Space)Msg 的入口,并对显式指定 ZHPS 的加密硬盘做后端拒绝或共享校验。

🔴 Critical

# File:Line Issue Fix Reviewer(s) Conf Route
1 storage/src/main/java/org/zstack/storage/volume/InstantiateVolumeForNewCreatedVmExtension.java:248; storage/src/main/java/org/zstack/storage/volume/VolumeManagerImpl.java:350 模板数据盘路径仍会绕过新过滤。InstantiateVolumeForNewCreatedVmExtension 在加密数据盘未指定 PS 时直接落到 defaultPsUuid,随后 VolumeManagerImplsetRequiredPrimaryStorageUuid(msg.getPrimaryStorageUuid()) 分配;若默认 PS 是 ZHPS,allocator 扩展没有机会过滤。独立 CreateDataVolumeFromVolumeTemplateMsg encrypted=true 且未指定 PS 时也没有设置 encryptedVolumeAutoAllocation Boolean.TRUE.equals(diskAO.getEncrypted()) && diskAO.getPrimaryStorageUuid() == null 的模板数据盘不要直接继承 defaultPsUuid;先用带 setEncryptedVolumeAutoAllocation(true) 的 dry-run/allocate 选择非 ZHPS,或在 CreateDataVolumeFromVolumeTemplateMsgAllocatePrimaryStorageSpaceMsg 的链路中传递该标志。同时对加密场景显式指定 ZHPS 的请求 fail-fast。补充覆盖“root 未加密但 template data disk 加密且自动选择”的测试。 correctness, robustness 0.91 gated_auto → downstream-resolver
2 compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java:53 挂载一个尚未实例化的加密云盘时仍可能自动分配到 ZHPS。该 flow 为 attach 路径创建 AllocatePrimaryStorageSpaceMsg,但没有根据 volume.getEncrypted() 设置本 MR 新增的标志,因此 PrimaryStorageAllocationSpec.isEncryptedVolumeAutoAllocation() 为 false,新增过滤扩展不会执行。 在该 flow 中设置 amsg.setEncryptedVolumeAutoAllocation(Boolean.TRUE.equals(volume.getEncrypted()) && volume.getPrimaryStorageUuid() == null),并增加“先创建 encrypted data volume、不指定 PS、再 attach 到 VM”时不会选择 ZHPS 的回归测试。 correctness, adversarial 0.88 gated_auto → downstream-resolver

🟡 Warning

# File:Line Issue Fix Reviewer(s) Conf Route
- - 未发现通过质量门槛的 Warning。 - - - -

🟢 Suggestion

# File:Line Issue Fix Reviewer(s) Conf Route
- - 未发现需要发布的 Suggestion。 - - - -

Coverage

  • Diff source: local git diff authoritative;MCP 与本地文件数一致,kept 10 / total 10,generated-file filter skipped 0。
  • Upstream freshness: target 分支在 merge-base 后新增 2 个 Ceph 相关提交,未改动本 MR 同文件;MR merge_status=can_be_merged
  • Verification: git diff --check 45e799eca5f9ee49ee064ba01dce35d613bff549..478e59b8e0b703de5b52ba797d03c29443206255 passed。未运行完整编译或集成测试。
  • Testing gaps: 当前新增单测只验证 extension 自身过滤,未覆盖模板数据盘、attach 未实例化加密盘、以及显式 ZHPS + encrypted 的端到端入口。
  • Residual risks: Jira 还要求迁移更改数据存储/主机+数据存储、以及前端候选项隐藏;本 MR diff 未覆盖这些入口。若已有其它 MR 负责,需要在描述中拆分 scope;否则该 Jira 不能仅靠本 MR close。

Verdict: REVISION_REQUIRED

2 条 Critical 都是修复不完整路径,可能让 encrypted=true + 自动选择主存储 继续落到 ZHPS。


🤖 Robot Reviewer

@ZStack-Robot

Copy link
Copy Markdown
Collaborator

Comment from 周众:

已修复:attach 未实例化加密盘补充 encryptedVolumeAutoAllocation;模板数据盘加密且自动选择时不再继承 defaultPsUuid,改为先通过 allocator dry-run 选择非 ZHPS,再继续原创建流程。过滤逻辑仍集中在 PrimaryStorageMainAllocatorFlow 的 filterPrimaryStorageCandidates 扩展点。

@MatheMatrix MatheMatrix force-pushed the sync/zstackio/codex/filter-zhps-encrypted-auto-ps branch 5 times, most recently from 2baeca6 to 0de0ff1 Compare July 8, 2026 05:40

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java (1)

149-149: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

加密自动分配判断逻辑在多个文件中重复。

Boolean.TRUE.equals(x.getEncrypted()) && x.getPrimaryStorageUuid() == null 这一表达式在本文件(根卷/数据卷)、VmAllocatePrimaryStorageForAttachingDiskFlowVmInstantiateOtherDiskFlow(两处)共出现 5 次。本 PR 的迭代历史本身就说明了这种重复的风险——review 过程中曾遗漏了附加磁盘与模板数据卷两处,需要额外补丁修复。建议抽取为统一的静态工具方法(例如 EncryptedVolumeAllocationUtils.isEncryptedAutoAllocation(Boolean encrypted, String primaryStorageUuid)),避免未来新增分配入口再次遗漏。

♻️ 建议的重构方向
+public class EncryptedVolumeAllocationUtils {
+    public static boolean isEncryptedAutoAllocation(Boolean encrypted, String primaryStorageUuid) {
+        return Boolean.TRUE.equals(encrypted) && primaryStorageUuid == null;
+    }
+}
-            rmsg.setEncryptedVolumeAutoAllocation(disk != null && Boolean.TRUE.equals(disk.getEncrypted()));
+            rmsg.setEncryptedVolumeAutoAllocation(disk != null
+                    && EncryptedVolumeAllocationUtils.isEncryptedAutoAllocation(disk.getEncrypted(), disk.getPrimaryStorageUuid()));

As per path instructions(## 6. 设计原则和模块划分 中的"单一职责原则"),应避免重复逻辑分散在多处、造成后续维护和一致性风险。

Also applies to: 184-186

🤖 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
`@compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java`
at line 149, The encrypted auto-allocation check is duplicated across multiple
VM primary-storage flows, so refactor it into one shared helper and reuse it
everywhere. Extract the repeated Boolean.TRUE.equals(encrypted) &&
primaryStorageUuid == null logic into a static utility such as
EncryptedVolumeAllocationUtils.isEncryptedAutoAllocation, then update
VmAllocatePrimaryStorageFlow, VmAllocatePrimaryStorageForAttachingDiskFlow, and
VmInstantiateOtherDiskFlow to call that helper instead of inlining the
condition. Keep the existing behavior identical while centralizing the rule to
prevent future misses in new allocation paths.

Source: Path instructions

test/src/test/java/org/zstack/test/unittest/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtensionTest.java (1)

16-92: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

缺少"加密根卷 + 自动分配主存储"场景的用例。

现有 4 个测试仅覆盖了 PrimaryStorageAllocationSpec 直接标记及 VmInstanceSpec 中非根盘(DiskAO.nonRootDisk() + 模板盘)两类场景,EncryptedVolumePrimaryStorageAllocatorExtension.isEncryptedAutoAllocatedRootVolume(根卷加密且 getCandidatePrimaryStorageUuidsForRootVolume() 为空)这条分支未被任何用例触发。考虑到根卷是加密自动分配最常见的入口之一,建议补充一个设置 spec.getRootDisk() 为加密盘、且未指定候选主存储的用例,以覆盖该分支并验证 getCandidatePrimaryStorageUuidsForRootVolume() 默认值的空安全性。

✅ 建议补充的测试用例示例
`@Test`
public void testFilterZhpsForEncryptedRootDiskWithAutoPrimaryStorage() {
    VmInstanceSpec spec = new VmInstanceSpec();
    DiskAO rootDisk = DiskAO.rootDisk(); // 视实际工厂方法调整
    rootDisk.setEncrypted(true);
    spec.setRootDisk(rootDisk);
    List<PrimaryStorageVO> candidates = new ArrayList<>(Arrays.asList(primaryStorage("normal-ps-uuid"), primaryStorage(ZHPS_PS_UUID)));

    extension.filterPrimaryStorageCandidates(spec, candidates);

    Assert.assertEquals(1, candidates.size());
    Assert.assertEquals("normal-ps-uuid", candidates.get(0).getUuid());
}
🤖 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/test/unittest/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtensionTest.java`
around lines 16 - 92, Add a test for the missing “encrypted root volume + auto
primary storage” path in EncryptedVolumePrimaryStorageAllocatorExtensionTest.
Introduce a case using VmInstanceSpec with an encrypted root disk via
DiskAO.rootDisk() (or the equivalent root-disk factory in this test) and no
explicit candidate primary storage, then call filterPrimaryStorageCandidates and
assert ZHPS_PS_UUID is filtered out. This should directly exercise
EncryptedVolumePrimaryStorageAllocatorExtension.isEncryptedAutoAllocatedRootVolume
and verify getCandidatePrimaryStorageUuidsForRootVolume() is safely handled when
unset.
🤖 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.

Inline comments:
In
`@storage/src/main/java/org/zstack/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtension.java`:
- Around line 56-65: `hasEncryptedAutoAllocatedVolume(VmInstanceSpec)` is using
the VM-wide `candidatePrimaryStorageUuidsForDataVolume` field inside a per-disk
check, which can incorrectly skip ZBS filtering in multi-disk cases. Refactor
the logic in `hasEncryptedAutoAllocatedVolume` so each deprecated disk is
evaluated independently: keep checking `isEncrypted(disk)` and
`disk.getPrimaryStorageUuid() == null`, but move the candidate-primary-storage
condition to disk-specific handling instead of relying on
`spec.getCandidatePrimaryStorageUuidsForDataVolume()` globally. Ensure the
helper still correctly detects auto-allocated encrypted root volumes via
`isEncryptedAutoAllocatedRootVolume` and only lets disks through when that
specific disk’s primary-storage selection warrants it.

---

Nitpick comments:
In
`@compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java`:
- Line 149: The encrypted auto-allocation check is duplicated across multiple VM
primary-storage flows, so refactor it into one shared helper and reuse it
everywhere. Extract the repeated Boolean.TRUE.equals(encrypted) &&
primaryStorageUuid == null logic into a static utility such as
EncryptedVolumeAllocationUtils.isEncryptedAutoAllocation, then update
VmAllocatePrimaryStorageFlow, VmAllocatePrimaryStorageForAttachingDiskFlow, and
VmInstantiateOtherDiskFlow to call that helper instead of inlining the
condition. Keep the existing behavior identical while centralizing the rule to
prevent future misses in new allocation paths.

In
`@test/src/test/java/org/zstack/test/unittest/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtensionTest.java`:
- Around line 16-92: Add a test for the missing “encrypted root volume + auto
primary storage” path in EncryptedVolumePrimaryStorageAllocatorExtensionTest.
Introduce a case using VmInstanceSpec with an encrypted root disk via
DiskAO.rootDisk() (or the equivalent root-disk factory in this test) and no
explicit candidate primary storage, then call filterPrimaryStorageCandidates and
assert ZHPS_PS_UUID is filtered out. This should directly exercise
EncryptedVolumePrimaryStorageAllocatorExtension.isEncryptedAutoAllocatedRootVolume
and verify getCandidatePrimaryStorageUuidsForRootVolume() is safely handled when
unset.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 052ff466-0332-4f2a-b612-3063562652a8

📥 Commits

Reviewing files that changed from the base of the PR and between cb00422 and 0de0ff1.

⛔ Files ignored due to path filters (1)
  • conf/springConfigXml/VolumeManager.xml is excluded by !**/*.xml
📒 Files selected for processing (11)
  • compute/src/main/java/org/zstack/compute/vm/VmAllocateHostAndPrimaryStorageFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmInstantiateOtherDiskFlow.java
  • header/src/main/java/org/zstack/header/storage/primary/AllocatePrimaryStorageMsg.java
  • header/src/main/java/org/zstack/header/storage/primary/PrimaryStorageAllocationSpec.java
  • header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java
  • storage/src/main/java/org/zstack/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtension.java
  • storage/src/main/java/org/zstack/storage/primary/PrimaryStorageMainAllocatorFlow.java
  • storage/src/main/java/org/zstack/storage/primary/PrimaryStorageManagerImpl.java
  • test/src/test/java/org/zstack/test/unittest/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtensionTest.java

@MatheMatrix MatheMatrix force-pushed the sync/zstackio/codex/filter-zhps-encrypted-auto-ps branch 2 times, most recently from dd70533 to 0af5fe5 Compare July 8, 2026 05:57
@MatheMatrix

Copy link
Copy Markdown
Owner

Comment from yaohua.wu:

Review: MR !10426 — ZSV-12607

Background

  • Jira: ZSV-12607 — 【硬盘加密】硬盘使用数据存储未zhps时 禁止开启硬盘加密
  • Bug summary: Jira 要求开启硬盘加密时不能把相关硬盘调度到 ZHPS,并特别提到创建/新增硬盘自动选择、迁移 VM 更改数据存储、迁移 VM 更改主机与数据存储等入口。
  • Intent & scope: 本 MR 通过 VmAllocatePrimaryStorageExtensionPointencryptedVolumeAutoAllocation 标记,在 VM 创建、attach、other disk/template disk 的自动主存储分配路径中过滤 ZHPS。
  • Round 1 initial findings: 1 × Critical,集中在 VM host+primary-storage 联合分配时 root/data 候选池被全局过滤的问题。
  • Suggested fix direction: 把 ZHPS 过滤从 VM 级全局候选池改成按卷角色/按卷粒度过滤,避免加密数据盘的自动分配约束误伤非加密根盘或显式选择的其他卷。

🔴 Critical

# File:Line Issue Fix Conf
1 storage/src/main/java/org/zstack/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtension.java:40 hasEncryptedAutoAllocatedVolume(spec) 只要发现任一加密盘需要自动分配,就在 filterPrimaryStorageCandidates(VmInstanceSpec...) 里把 ZHPS 从 available/local/nonLocal 三个 VM 级共享列表全部删除。随后 VmAllocateHostAndPrimaryStorageFlow 会用这个已过滤的 availablePsUuids 校验 root/data 的显式候选,并用同一批 local/nonLocal 生成 root/data 组合。因此“非加密 root 显式在 ZHPS + 加密 data 自动分配到普通 PS”这类可达组合会被错误拒绝:root 候选 ZHPS 在进入组合前已经被删掉,但只有加密数据盘才需要避开 ZHPS。 不要在 VM 级共享列表上一次性删除 ZHPS。将过滤改为按角色/按卷粒度:先区分 rootNeedsEncryptedAutoPsFilterdataNeedsEncryptedAutoPsFilter,再分别过滤 root 候选池和 data 候选池;或者调整扩展点签名,让调用方传入 root/data 两套候选列表。补一个用例覆盖:root 非加密且指定 ZHPS、data 加密且自动分配时,仍能生成 root=ZHPS, data=non-ZHPS 的组合;同时保留加密 root 自动分配时过滤 ZHPS 的用例。 0.91

Coverage

  • 本地 diff 与 MCP diff 交叉校验:12/12 个文件一致,未发现空 diff;generated-file filter 跳过 0 个文件。
  • Upstream freshness:feature-zsv-5.1.0-encryption 相对源分支无新增未合入提交,MR 状态 can_be_merged
  • Verification:已跑 git diff --check,无输出。
  • Residual risk:Jira 还提到前端候选列表/迁移入口禁止选择 ZHPS;当前后端候选查询 API 没有加密开关参数,本轮未把它作为当前 Java diff 的确定性 finding。

Verdict: REVISION_REQUIRED

当前实现会在混合 root/data 场景中过度过滤 ZHPS,导致合法的非加密卷放置被拒绝,需要按卷粒度修正后再合入。


🤖 Robot Reviewer

@MatheMatrix MatheMatrix force-pushed the sync/zstackio/codex/filter-zhps-encrypted-auto-ps branch 10 times, most recently from 2a98582 to 62968b9 Compare July 8, 2026 08:42
@MatheMatrix MatheMatrix force-pushed the sync/zstackio/codex/filter-zhps-encrypted-auto-ps branch 3 times, most recently from 8f57445 to 1c435db Compare July 15, 2026 12:21

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java (1)

66-68: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

逻辑正确,但与其他文件存在重复模式。

该「加密且未指定主存储则追加 ENCRYPTED_VOLUME 特性」的判断逻辑,在 VolumeManagerImpl.java(364-366行)及 VmAllocatePrimaryStorageFlow.java 中重复出现。建议抽取为 AllocatePrimaryStorageMsg/AllocatePrimaryStorageSpaceMsg 上的统一辅助方法,减少重复并降低未来修改遗漏的风险(详见文末合并意见)。

🤖 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
`@compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java`
around lines 66 - 68, 将“卷已加密且未指定主存储时追加 ENCRYPTED_VOLUME 特性”的重复判断抽取到
AllocatePrimaryStorageMsg 或 AllocatePrimaryStorageSpaceMsg 的统一辅助方法中;更新
VmAllocatePrimaryStorageForAttachingDiskFlow 及
VolumeManagerImpl、VmAllocatePrimaryStorageFlow 使用该方法,并移除各处重复条件逻辑,保持现有行为不变。
test/src/test/groovy/org/zstack/test/integration/storage/primary/EncryptedVolumePrimaryStorageAllocationCase.groovy (1)

59-93: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

缺少针对 VM 级根/数据盘混合场景的回归测试。

当前测试仅覆盖了 AllocatePrimaryStorageSpaceMsg + PrimaryStorageFeatureAllocatorExtensionPoint.allocatePrimaryStorage 这一条路径,未覆盖 VmAllocatePrimaryStorageExtensionPoint.filterPrimaryStorageCandidates(VM 级 root/data 候选过滤)路径,也未覆盖 PR 目标中提到的混合场景(非加密根盘显式放在 ZBS,加密数据盘放在非 ZBS)。建议补充一个通过完整 VM 创建流程触发 filterPrimaryStorageCandidates 的集成测试用例,以验证 root 与 data 候选列表按卷角色独立过滤,而不是全部包含关系。

🤖 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/groovy/org/zstack/test/integration/storage/primary/EncryptedVolumePrimaryStorageAllocationCase.groovy`
around lines 59 - 93, 在现有测试类中新增一个通过完整 VM 创建流程触发
VmAllocatePrimaryStorageExtensionPoint.filterPrimaryStorageCandidates
的集成测试,覆盖非加密根盘显式放在 ZBS、加密数据盘放在非 ZBS 的混合场景。分别断言 root 与 data
卷候选按各自卷角色独立过滤,确保不会错误地使用所有卷候选的整体包含关系;保留现有
testFilterZhpsForEncryptedVolumeAutoAllocation 的覆盖范围不变。
storage/src/main/java/org/zstack/storage/volume/VolumeManagerImpl.java (1)

364-366: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

逻辑正确,但与其他文件存在重复模式。

VmAllocatePrimaryStorageForAttachingDiskFlow.java 66-68行的重复问题,见文末合并意见。

🤖 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 `@storage/src/main/java/org/zstack/storage/volume/VolumeManagerImpl.java`
around lines 364 - 366, 将 VolumeManagerImpl 中针对加密卷且未指定主存储时添加
PrimaryStorageFeature.ENCRYPTED_VOLUME 的逻辑,与
VmAllocatePrimaryStorageForAttachingDiskFlow
中的重复实现提取为共享方法或复用已有公共方法,并让两处调用该实现;保持现有判断条件和 amsg.addRequiredFeature 行为不变。
🤖 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.

Inline comments:
In
`@header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java`:
- Around line 5-8: 为公共接口方法
VmAllocatePrimaryStorageExtensionPoint.filterPrimaryStorageCandidates 补充有效
Javadoc,说明其调用时机、spec 参数用途、rootPrimaryStorageUuids 与 dataPrimaryStorageUuids
分别表示的候选列表,以及实现应原地修改列表的约定。

In `@storage/src/main/java/org/zstack/storage/volume/VolumeBase.java`:
- Around line 3414-3420: 修改 refreshVO() 的异常处理:刷新失败时不要仅记录警告后继续执行
trigger.next(),应按现有流程重试刷新,或继续向上抛出异常使流程失败。只有 refreshVO() 成功后才允许调用
trigger.next(),确保后续结果不会使用过期的 self。
- Around line 3466-3473: 严格处理加密转换后的清理失败:更新
detachKeyProviderFromVolume、detachKeyProviderFromSnapshot 及 trash.createTrash
所在流程,失败时执行可重试处理或持久化待清理任务,不要仅记录日志后继续成功返回;确保密钥引用解绑和旧数据位回收状态可被可靠完成或追踪。

---

Nitpick comments:
In
`@compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java`:
- Around line 66-68: 将“卷已加密且未指定主存储时追加 ENCRYPTED_VOLUME 特性”的重复判断抽取到
AllocatePrimaryStorageMsg 或 AllocatePrimaryStorageSpaceMsg 的统一辅助方法中;更新
VmAllocatePrimaryStorageForAttachingDiskFlow 及
VolumeManagerImpl、VmAllocatePrimaryStorageFlow 使用该方法,并移除各处重复条件逻辑,保持现有行为不变。

In `@storage/src/main/java/org/zstack/storage/volume/VolumeManagerImpl.java`:
- Around line 364-366: 将 VolumeManagerImpl 中针对加密卷且未指定主存储时添加
PrimaryStorageFeature.ENCRYPTED_VOLUME 的逻辑,与
VmAllocatePrimaryStorageForAttachingDiskFlow
中的重复实现提取为共享方法或复用已有公共方法,并让两处调用该实现;保持现有判断条件和 amsg.addRequiredFeature 行为不变。

In
`@test/src/test/groovy/org/zstack/test/integration/storage/primary/EncryptedVolumePrimaryStorageAllocationCase.groovy`:
- Around line 59-93: 在现有测试类中新增一个通过完整 VM 创建流程触发
VmAllocatePrimaryStorageExtensionPoint.filterPrimaryStorageCandidates
的集成测试,覆盖非加密根盘显式放在 ZBS、加密数据盘放在非 ZBS 的混合场景。分别断言 root 与 data
卷候选按各自卷角色独立过滤,确保不会错误地使用所有卷候选的整体包含关系;保留现有
testFilterZhpsForEncryptedVolumeAutoAllocation 的覆盖范围不变。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4a5412c8-388d-4cc9-9877-e937c0d719d6

📥 Commits

Reviewing files that changed from the base of the PR and between 0de0ff1 and 1c435db.

⛔ Files ignored due to path filters (1)
  • conf/springConfigXml/VolumeManager.xml is excluded by !**/*.xml
📒 Files selected for processing (12)
  • compute/src/main/java/org/zstack/compute/vm/VmAllocateHostAndPrimaryStorageFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmInstantiateOtherDiskFlow.java
  • header/src/main/java/org/zstack/header/storage/primary/AllocatePrimaryStorageMsg.java
  • header/src/main/java/org/zstack/header/storage/primary/PrimaryStorageFeature.java
  • header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java
  • storage/src/main/java/org/zstack/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtension.java
  • storage/src/main/java/org/zstack/storage/volume/InstantiateVolumeForNewCreatedVmExtension.java
  • storage/src/main/java/org/zstack/storage/volume/VolumeBase.java
  • storage/src/main/java/org/zstack/storage/volume/VolumeManagerImpl.java
  • test/src/test/groovy/org/zstack/test/integration/storage/primary/EncryptedVolumePrimaryStorageAllocationCase.groovy
🚧 Files skipped from review as they are similar to previous changes (1)
  • compute/src/main/java/org/zstack/compute/vm/VmInstantiateOtherDiskFlow.java

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 3

🧹 Nitpick comments (3)
compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java (1)

66-68: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

逻辑正确,但与其他文件存在重复模式。

该「加密且未指定主存储则追加 ENCRYPTED_VOLUME 特性」的判断逻辑,在 VolumeManagerImpl.java(364-366行)及 VmAllocatePrimaryStorageFlow.java 中重复出现。建议抽取为 AllocatePrimaryStorageMsg/AllocatePrimaryStorageSpaceMsg 上的统一辅助方法,减少重复并降低未来修改遗漏的风险(详见文末合并意见)。

🤖 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
`@compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java`
around lines 66 - 68, 将“卷已加密且未指定主存储时追加 ENCRYPTED_VOLUME 特性”的重复判断抽取到
AllocatePrimaryStorageMsg 或 AllocatePrimaryStorageSpaceMsg 的统一辅助方法中;更新
VmAllocatePrimaryStorageForAttachingDiskFlow 及
VolumeManagerImpl、VmAllocatePrimaryStorageFlow 使用该方法,并移除各处重复条件逻辑,保持现有行为不变。
test/src/test/groovy/org/zstack/test/integration/storage/primary/EncryptedVolumePrimaryStorageAllocationCase.groovy (1)

59-93: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

缺少针对 VM 级根/数据盘混合场景的回归测试。

当前测试仅覆盖了 AllocatePrimaryStorageSpaceMsg + PrimaryStorageFeatureAllocatorExtensionPoint.allocatePrimaryStorage 这一条路径,未覆盖 VmAllocatePrimaryStorageExtensionPoint.filterPrimaryStorageCandidates(VM 级 root/data 候选过滤)路径,也未覆盖 PR 目标中提到的混合场景(非加密根盘显式放在 ZBS,加密数据盘放在非 ZBS)。建议补充一个通过完整 VM 创建流程触发 filterPrimaryStorageCandidates 的集成测试用例,以验证 root 与 data 候选列表按卷角色独立过滤,而不是全部包含关系。

🤖 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/groovy/org/zstack/test/integration/storage/primary/EncryptedVolumePrimaryStorageAllocationCase.groovy`
around lines 59 - 93, 在现有测试类中新增一个通过完整 VM 创建流程触发
VmAllocatePrimaryStorageExtensionPoint.filterPrimaryStorageCandidates
的集成测试,覆盖非加密根盘显式放在 ZBS、加密数据盘放在非 ZBS 的混合场景。分别断言 root 与 data
卷候选按各自卷角色独立过滤,确保不会错误地使用所有卷候选的整体包含关系;保留现有
testFilterZhpsForEncryptedVolumeAutoAllocation 的覆盖范围不变。
storage/src/main/java/org/zstack/storage/volume/VolumeManagerImpl.java (1)

364-366: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

逻辑正确,但与其他文件存在重复模式。

VmAllocatePrimaryStorageForAttachingDiskFlow.java 66-68行的重复问题,见文末合并意见。

🤖 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 `@storage/src/main/java/org/zstack/storage/volume/VolumeManagerImpl.java`
around lines 364 - 366, 将 VolumeManagerImpl 中针对加密卷且未指定主存储时添加
PrimaryStorageFeature.ENCRYPTED_VOLUME 的逻辑,与
VmAllocatePrimaryStorageForAttachingDiskFlow
中的重复实现提取为共享方法或复用已有公共方法,并让两处调用该实现;保持现有判断条件和 amsg.addRequiredFeature 行为不变。
🤖 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.

Inline comments:
In
`@header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java`:
- Around line 5-8: 为公共接口方法
VmAllocatePrimaryStorageExtensionPoint.filterPrimaryStorageCandidates 补充有效
Javadoc,说明其调用时机、spec 参数用途、rootPrimaryStorageUuids 与 dataPrimaryStorageUuids
分别表示的候选列表,以及实现应原地修改列表的约定。

In `@storage/src/main/java/org/zstack/storage/volume/VolumeBase.java`:
- Around line 3414-3420: 修改 refreshVO() 的异常处理:刷新失败时不要仅记录警告后继续执行
trigger.next(),应按现有流程重试刷新,或继续向上抛出异常使流程失败。只有 refreshVO() 成功后才允许调用
trigger.next(),确保后续结果不会使用过期的 self。
- Around line 3466-3473: 严格处理加密转换后的清理失败:更新
detachKeyProviderFromVolume、detachKeyProviderFromSnapshot 及 trash.createTrash
所在流程,失败时执行可重试处理或持久化待清理任务,不要仅记录日志后继续成功返回;确保密钥引用解绑和旧数据位回收状态可被可靠完成或追踪。

---

Nitpick comments:
In
`@compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java`:
- Around line 66-68: 将“卷已加密且未指定主存储时追加 ENCRYPTED_VOLUME 特性”的重复判断抽取到
AllocatePrimaryStorageMsg 或 AllocatePrimaryStorageSpaceMsg 的统一辅助方法中;更新
VmAllocatePrimaryStorageForAttachingDiskFlow 及
VolumeManagerImpl、VmAllocatePrimaryStorageFlow 使用该方法,并移除各处重复条件逻辑,保持现有行为不变。

In `@storage/src/main/java/org/zstack/storage/volume/VolumeManagerImpl.java`:
- Around line 364-366: 将 VolumeManagerImpl 中针对加密卷且未指定主存储时添加
PrimaryStorageFeature.ENCRYPTED_VOLUME 的逻辑,与
VmAllocatePrimaryStorageForAttachingDiskFlow
中的重复实现提取为共享方法或复用已有公共方法,并让两处调用该实现;保持现有判断条件和 amsg.addRequiredFeature 行为不变。

In
`@test/src/test/groovy/org/zstack/test/integration/storage/primary/EncryptedVolumePrimaryStorageAllocationCase.groovy`:
- Around line 59-93: 在现有测试类中新增一个通过完整 VM 创建流程触发
VmAllocatePrimaryStorageExtensionPoint.filterPrimaryStorageCandidates
的集成测试,覆盖非加密根盘显式放在 ZBS、加密数据盘放在非 ZBS 的混合场景。分别断言 root 与 data
卷候选按各自卷角色独立过滤,确保不会错误地使用所有卷候选的整体包含关系;保留现有
testFilterZhpsForEncryptedVolumeAutoAllocation 的覆盖范围不变。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4a5412c8-388d-4cc9-9877-e937c0d719d6

📥 Commits

Reviewing files that changed from the base of the PR and between 0de0ff1 and 1c435db.

⛔ Files ignored due to path filters (1)
  • conf/springConfigXml/VolumeManager.xml is excluded by !**/*.xml
📒 Files selected for processing (12)
  • compute/src/main/java/org/zstack/compute/vm/VmAllocateHostAndPrimaryStorageFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmAllocatePrimaryStorageForAttachingDiskFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmInstantiateOtherDiskFlow.java
  • header/src/main/java/org/zstack/header/storage/primary/AllocatePrimaryStorageMsg.java
  • header/src/main/java/org/zstack/header/storage/primary/PrimaryStorageFeature.java
  • header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java
  • storage/src/main/java/org/zstack/storage/encrypt/EncryptedVolumePrimaryStorageAllocatorExtension.java
  • storage/src/main/java/org/zstack/storage/volume/InstantiateVolumeForNewCreatedVmExtension.java
  • storage/src/main/java/org/zstack/storage/volume/VolumeBase.java
  • storage/src/main/java/org/zstack/storage/volume/VolumeManagerImpl.java
  • test/src/test/groovy/org/zstack/test/integration/storage/primary/EncryptedVolumePrimaryStorageAllocationCase.groovy
🚧 Files skipped from review as they are similar to previous changes (1)
  • compute/src/main/java/org/zstack/compute/vm/VmInstantiateOtherDiskFlow.java
🛑 Comments failed to post (3)
header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java (1)

5-8: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

为公共扩展点方法补充 Javadoc。

filterPrimaryStorageCandidates 是跨模块扩展契约,但目前没有说明调用时机、root/data 两组候选列表的含义,以及实现是否应原地修改列表,容易导致扩展实现产生不一致行为。

As per path instructions:接口方法必须配有有效的 Javadoc 注释。

建议补充
 public interface VmAllocatePrimaryStorageExtensionPoint {
+    /**
+     * 在生成主存储组合前过滤 root/data 主存储候选。
+     *
+     * `@param` spec VM 分配规格
+     * `@param` rootPrimaryStorageUuids root 卷候选主存储 UUID,允许原地过滤
+     * `@param` dataPrimaryStorageUuids data 卷候选主存储 UUID,允许原地过滤
+     */
     default void filterPrimaryStorageCandidates(VmInstanceSpec spec, List<String> rootPrimaryStorageUuids,
                                                  List<String> dataPrimaryStorageUuids) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

public interface VmAllocatePrimaryStorageExtensionPoint {
    /**
     * 在生成主存储组合前过滤 root/data 主存储候选。
     *
     * `@param` spec VM 分配规格
     * `@param` rootPrimaryStorageUuids root 卷候选主存储 UUID,允许原地过滤
     * `@param` dataPrimaryStorageUuids data 卷候选主存储 UUID,允许原地过滤
     */
    default void filterPrimaryStorageCandidates(VmInstanceSpec spec, List<String> rootPrimaryStorageUuids,
                                                List<String> dataPrimaryStorageUuids) {
    }
🤖 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
`@header/src/main/java/org/zstack/header/vm/VmAllocatePrimaryStorageExtensionPoint.java`
around lines 5 - 8, 为公共接口方法
VmAllocatePrimaryStorageExtensionPoint.filterPrimaryStorageCandidates 补充有效
Javadoc,说明其调用时机、spec 参数用途、rootPrimaryStorageUuids 与 dataPrimaryStorageUuids
分别表示的候选列表,以及实现应原地修改列表的约定。

Source: Coding guidelines

storage/src/main/java/org/zstack/storage/volume/VolumeBase.java (2)

3414-3420: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

不要吞掉 refreshVO() 失败。

Line [3414] 之后即使刷新失败仍执行 trigger.next();但数据库更新已经完成,最终 Line [3501] 会用过期的 self 返回成功结果,可能继续报告旧的 encrypted 状态或旧安装路径。应重试刷新,或让流程失败而不是返回过期 inventory。

As per path instructions:异常不能被静默转换为正常流程,必要时应继续向上抛出。

🤖 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 `@storage/src/main/java/org/zstack/storage/volume/VolumeBase.java` around lines
3414 - 3420, 修改 refreshVO() 的异常处理:刷新失败时不要仅记录警告后继续执行
trigger.next(),应按现有流程重试刷新,或继续向上抛出异常使流程失败。只有 refreshVO() 成功后才允许调用
trigger.next(),确保后续结果不会使用过期的 self。

Source: Coding guidelines


3466-3473: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

不要把密钥引用和旧位清理失败转成成功。

数据库在 Line [3763] 已更新卷的加密状态;如果 detachKeyProviderFromVolume、快照密钥解绑或 trash.createTrash 失败,当前代码只记录日志并继续,最终会出现“数据库显示转换成功,但密钥引用仍存在或旧数据位未纳入回收”的不一致状态。请改为失败重试,或持久化待清理任务。

As per path instructions:应严格处理异常,不能将关键资源清理失败当作正常流程。

Also applies to: 3484-3493

🤖 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 `@storage/src/main/java/org/zstack/storage/volume/VolumeBase.java` around lines
3466 - 3473, 严格处理加密转换后的清理失败:更新
detachKeyProviderFromVolume、detachKeyProviderFromSnapshot 及 trash.createTrash
所在流程,失败时执行可重试处理或持久化待清理任务,不要仅记录日志后继续成功返回;确保密钥引用解绑和旧数据位回收状态可被可靠完成或追踪。

Source: Coding guidelines

@MatheMatrix MatheMatrix force-pushed the sync/zstackio/codex/filter-zhps-encrypted-auto-ps branch 2 times, most recently from dfee7fa to feacb8d Compare July 15, 2026 13:48
Filter zhps in the allocator extension point.

Only applies to encrypted auto primary storage allocation.

Test: git diff --check

Test: cbok zsv compile --no-deploy passed

Test: cbok zsv groovy_test EncryptedVolumePrimaryStorageAllocationCase passed

Resolves: ZSV-12607

Change-Id: If4078641c7a42c67552373fcc9d7581cf4f97b1a
@MatheMatrix MatheMatrix force-pushed the sync/zstackio/codex/filter-zhps-encrypted-auto-ps branch from feacb8d to 92b7973 Compare July 15, 2026 14:20
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.

3 participants