Skip to content

<refactor>[kvm]: improve TPM removal by cleaning host files before DB deletion#3667

Closed
MatheMatrix wants to merge 1 commit into
feature-zsv-5.0.0-vm-support-vtpm-and-secucebootfrom
sync/wenhao.zhang/zsv-ldap-4
Closed

<refactor>[kvm]: improve TPM removal by cleaning host files before DB deletion#3667
MatheMatrix wants to merge 1 commit into
feature-zsv-5.0.0-vm-support-vtpm-and-secucebootfrom
sync/wenhao.zhang/zsv-ldap-4

Conversation

@MatheMatrix

Copy link
Copy Markdown
Owner

Refactor the removeTpmFromVm method to split the DB removal flow
into three steps for better resource cleanup:

  1. Collect VmHostFileVO and VmHostBackupFileVO for TPM state files
  2. Send delete commands to hosts to clean up files on disk
  3. Remove database records regardless of command success

This ensures host files are cleaned up before DB records are deleted.
Removed NvRam file deletion to avoid conflicts with secure boot.

Related: ZSV-11310
Resolves: ZSV-11622

Change-Id: I7865626a687376746c746a706b74676b6b7a6a71

sync from gitlab !9527

@coderabbitai

coderabbitai Bot commented Apr 2, 2026

Copy link
Copy Markdown

Walkthrough

KvmTpmManager.removeTpmFromVm 的控制流重构:先查询并保存 VmHostFileType.TpmState 主机端文件记录,按 hostUuid 分组并逐主机下发 WriteVmHostFileContentCmd 删除命令(失败仅记录日志),随后执行数据库清理,仅删除 TpmState 类型的 VmHostFileVO/VmHostBackupFileVO 以及对应的 TpmVO。同时更新导入以使用 HashMap 和 KVM 命令相关类型。

Changes

Cohort / File(s) Summary
TPM 移除流程重构
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
重构 removeTpmFromVm:新增查询并收集 VmHostFileType.TpmState 记录、按主机分组并发送每主机 WriteVmHostFileContentCmd 删除操作;主机命令失败仅记录日志并继续;将数据库清理阶段重命名为 remove-db-records,仅删除 TpmState 类型的 VmHostFileVO/VmHostBackupFileVO 和相关 TpmVO;更新 imports(引入 HashMap 与 KVM 命令/response 类型)。

Sequence Diagram(s)

sequenceDiagram
    participant Manager as KvmTpmManager
    participant DB as Database
    participant Host as KVM Host Agent

    Manager->>DB: 查询 `VmHostFileVO` (type=TpmState) for VM
    DB-->>Manager: 返回 hostFiles 列表
    Manager->>Manager: 按 hostUuid 分组 hostFiles
    loop 每个 host
        Manager->>Host: WriteVmHostFileContentCmd(delete paths)
        alt host 成功
            Host-->>Manager: WriteVmHostFileContentRsp(success)
        else host 失败
            Host-->>Manager: WriteVmHostFileContentRsp(failure)
            Manager-->>Manager: 记录警告,不中断流程
        end
    end
    Manager->>DB: 删除 `TpmVO` 与 `VmHostFileVO`/`VmHostBackupFileVO` (type=TpmState)
    DB-->>Manager: 删除完成
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 主机文件分组来清理,逐个下发不慌张,
错误只写成日志条,数据库再轻轻擦光,
小兔一跳挥爪去,TPM 问题已散场。

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Title check ✅ Passed 标题准确地总结了主要变更,即改进TPM移除流程以在数据库删除前进行主机文件清理。
Description check ✅ Passed 描述与变更集相关,清楚地说明了三步流程和移除NvRam删除的原因,虽然未完全反映审查意见中提出的问题。

✏️ 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/wenhao.zhang/zsv-ldap-4

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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

@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 (1)
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java (1)

356-359: 可选优化:使用 Stream API 进行分组。

当前使用 for 循环配合 computeIfAbsent 进行分组,可以考虑使用 Java Stream 的 Collectors.groupingBy 使代码更简洁。

♻️ 可选重构建议
-                    Map<String, List<VmHostFileVO>> filesByHost = new HashMap<>();
-                    for (VmHostFileVO file : context.hostFiles) {
-                        filesByHost.computeIfAbsent(file.getHostUuid(), k -> new ArrayList<>()).add(file);
-                    }
+                    Map<String, List<VmHostFileVO>> filesByHost = context.hostFiles.stream()
+                            .collect(java.util.stream.Collectors.groupingBy(VmHostFileVO::getHostUuid));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java` around lines
356 - 359, Replace the manual grouping loop in KvmTpmManager that builds
filesByHost from context.hostFiles using computeIfAbsent with a Stream-based
collect: use
context.hostFiles.stream().collect(Collectors.groupingBy(VmHostFileVO::getHostUuid))
to produce Map<String, List<VmHostFileVO>> filesByHost; add the necessary import
for java.util.stream.Collectors and ensure the variable type remains Map<String,
List<VmHostFileVO>> so existing code using filesByHost continues to work.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Around line 356-359: Replace the manual grouping loop in KvmTpmManager that
builds filesByHost from context.hostFiles using computeIfAbsent with a
Stream-based collect: use
context.hostFiles.stream().collect(Collectors.groupingBy(VmHostFileVO::getHostUuid))
to produce Map<String, List<VmHostFileVO>> filesByHost; add the necessary import
for java.util.stream.Collectors and ensure the variable type remains Map<String,
List<VmHostFileVO>> so existing code using filesByHost continues to work.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8b6689c6-e594-4943-9fb5-ad03cc5286dc

📥 Commits

Reviewing files that changed from the base of the PR and between 2a5980b and 8663f8b.

📒 Files selected for processing (1)
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java

@ZStack-Robot

Copy link
Copy Markdown
Collaborator

Comment from ye.zou:

Code Review

# 严重程度 分类 文件 问题描述 修复建议
1 🟡 Major 正确性 KvmTpmManager.java:send-delete-commands-to-hosts detach-resource-key flow 在 send-delete-commands-to-hosts 之前执行,且没有 rollback。如果 KVM 删除命令全部失败(比如所有 host 都不可达),key 已经 detach 了但 TPM 文件还在 host 上,后续也没有机制重新关联。虽然 DB 记录最终会被删掉,但 host 上残留的 TPM state 文件失去了 key 保护 考虑将 detach-resource-key 移到 KVM 命令之后、DB 删除之前;或者给 detach-resource-key 加 rollback(失败时重新 attach)
2 🟡 Major 向后兼容 KvmTpmManager.java:remove-db-records 老代码在 needRegisterNvRam 返回 false 时会同时删除 NvRam 类型的 VmHostFileVOVmHostBackupFileVO。新代码完全移除了 NvRam 清理逻辑。如果之前已经有 VM 处于"有 TPM 无 secure boot"的状态,移除 TPM 后 NvRam 文件会永久残留(DB 记录 + host 文件),因为没有其他地方会清理它 如果确认 NvRam 的生命周期已由 VmHostFileTracker 的 cleanup 任务管理(MR !9525),在注释中标明依赖关系;否则需要保留条件删除逻辑
3 🔵 Minor 代码质量 KvmTpmManager.java:RemoveTpmFromVmContext context.backupFiles 被收集但从未使用。collect-vm-host-files flow 查询了 VmHostBackupFileVO 存入 context.backupFiles,但 send-delete-commands-to-hosts 只处理 context.hostFiles,backup files 没有发删除命令 要么在 send-delete-commands-to-hosts 中也处理 backup files 的 host 删除,要么不查询 backup files(DB 删除在 remove-db-records 里已有)
4 🔵 Minor 代码质量 KvmTpmManager.java:send-delete-commands-to-hosts host 不可达时只 warn 但继续执行 DB 删除。这是有意设计(MR 描述说"Remove database records regardless of command success"),但没有在 Flow 名称或注释中体现这个"best-effort"语义 在 Flow 名字或注释中明确说明是 best-effort cleanup

结论: CONDITIONAL ⚠️
回归风险: 低 — 改动范围限于 TPM 移除流程,不影响 TPM 创建/克隆/secure boot
修复建议: #1 建议评估(key detach 顺序),#2 需确认 NvRam 残留是否可接受,#3 应清理未使用的 backupFiles 字段

… deletion

Refactor the removeTpmFromVm method to split the DB removal flow
into three steps for better resource cleanup:

1. Collect VmHostFileVO and VmHostBackupFileVO for TPM state files
2. Send delete commands to hosts to clean up files on disk
3. Remove database records regardless of command success

This ensures host files are cleaned up before DB records are deleted.
Removed NvRam file deletion to avoid conflicts with secure boot.

Related: ZSV-11310
Resolves: ZSV-11622

Change-Id: I7865626a687376746c746a706b74676b6b7a6a71
@MatheMatrix MatheMatrix force-pushed the sync/wenhao.zhang/zsv-ldap-4 branch from 8663f8b to efc4fc2 Compare April 2, 2026 08:42

@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

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java (2)

387-413: ⚠️ Potential issue | 🟠 Major

关于 detach-resource-key 与主机删除命令失败的场景。

当前流程顺序:send-delete-commands-to-hostsdetach-resource-keyremove-db-records

潜在风险:如果所有主机删除命令都失败(如主机不可达),流程仍会继续执行:

  1. 解除密钥绑定(detach-resource-key
  2. 删除数据库记录

这会导致 TPM 状态文件残留在主机上但失去密钥保护。

建议评估以下方案之一:

  1. detach-resource-key 步骤添加回滚逻辑,如果后续失败可重新绑定密钥;
  2. 如果认为这是可接受的 trade-off(优先保证 DB 一致性),请添加注释说明设计意图。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java` around lines
387 - 413, The detach-resource-key step (Flow.of("detach-resource-key") using
tpmKeyBackend.detachKeyProviderFromTpm(context.tpmUuid)) executes
unconditionally after send-delete-commands-to-hosts and before
remove-db-records, which can leave TPM state files on hosts unprotected if all
host delete commands failed; either implement rollback binding (capture result
of host deletes and, on downstream failure, call
tpmKeyBackend.attachKeyProviderToTpm or equivalent during error/compensation) so
detach is reversible, or if the intended design is to prefer DB consistency over
host state, add a clear comment near Flow.of("detach-resource-key") and
Flow.of("remove-db-records") referencing send-delete-commands-to-hosts to
document the trade-off and why detach proceeds despite host delete failures.

299-310: ⚠️ Potential issue | 🟡 Minor

VmHostBackupFileVO 处理不一致。

context.hostFiles 仅收集 VmHostFileVO,但在 remove-db-records 流程中同时删除了 VmHostBackupFileVO 的数据库记录(第 405-408 行)。然而,send-delete-commands-to-hosts 流程仅对 hostFiles 发送删除命令,未包含备份文件。

这会导致备份文件的主机端文件成为孤立文件,建议:

  1. collect-vm-host-files 中同时收集 VmHostBackupFileVO 并在主机端删除;或
  2. 如果备份文件由其他机制清理(如 VmHostFileTracker),请移除对 VmHostBackupFileVO 的查询和删除,或添加注释说明。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java` around lines
299 - 310, The RemoveTpmFromVmContext currently only collects VmHostFileVO into
context.hostFiles but remove-db-records also deletes VmHostBackupFileVO entries,
leading to orphaned host files; update the collect-vm-host-files flow to also
query and include VmHostBackupFileVO into the context (e.g., add a separate list
like backupHostFiles on RemoveTpmFromVmContext) and extend
send-delete-commands-to-hosts to send delete commands for those backup files as
well, or alternatively remove the VmHostBackupFileVO query/deletion in
remove-db-records or add a clear comment explaining that backup files are
cleaned by another mechanism (refer to RemoveTpmFromVmContext, hostFiles,
collect-vm-host-files, send-delete-commands-to-hosts, remove-db-records,
VmHostBackupFileVO, VmHostFileVO).
🧹 Nitpick comments (1)
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java (1)

339-386: 建议添加注释说明 "best-effort" 语义。

当前实现在主机删除命令失败时仅记录警告并继续(第 373-377 行),这是预期的容错设计。但代码中缺少对此语义的说明,后续维护者可能误解为遗漏错误处理。

建议在流程开头或失败处理处添加简短注释:

 .then(Flow.of("send-delete-commands-to-hosts")
+    // Best-effort: host command failures are tolerated to ensure DB cleanup proceeds.
     .skipIf(data -> context.hostFiles.isEmpty())
     .handle(trigger -> {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java` around lines
339 - 386, Add a short, clear comment in KvmTpmManager describing that the
"send-delete-commands-to-hosts" flow performs best-effort cleanup: when
KvmCommandSender.send(...) for WriteVmHostFileContentCmd fails the code
intentionally logs a warning in the ReturnValueCompletion.fail(...) block and
continues DB cleanup; place the comment either at the start of the
Flow.of("send-delete-commands-to-hosts") block or immediately above the
fail(...) handler to document that failures are non-fatal and expected behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Around line 387-413: The detach-resource-key step
(Flow.of("detach-resource-key") using
tpmKeyBackend.detachKeyProviderFromTpm(context.tpmUuid)) executes
unconditionally after send-delete-commands-to-hosts and before
remove-db-records, which can leave TPM state files on hosts unprotected if all
host delete commands failed; either implement rollback binding (capture result
of host deletes and, on downstream failure, call
tpmKeyBackend.attachKeyProviderToTpm or equivalent during error/compensation) so
detach is reversible, or if the intended design is to prefer DB consistency over
host state, add a clear comment near Flow.of("detach-resource-key") and
Flow.of("remove-db-records") referencing send-delete-commands-to-hosts to
document the trade-off and why detach proceeds despite host delete failures.
- Around line 299-310: The RemoveTpmFromVmContext currently only collects
VmHostFileVO into context.hostFiles but remove-db-records also deletes
VmHostBackupFileVO entries, leading to orphaned host files; update the
collect-vm-host-files flow to also query and include VmHostBackupFileVO into the
context (e.g., add a separate list like backupHostFiles on
RemoveTpmFromVmContext) and extend send-delete-commands-to-hosts to send delete
commands for those backup files as well, or alternatively remove the
VmHostBackupFileVO query/deletion in remove-db-records or add a clear comment
explaining that backup files are cleaned by another mechanism (refer to
RemoveTpmFromVmContext, hostFiles, collect-vm-host-files,
send-delete-commands-to-hosts, remove-db-records, VmHostBackupFileVO,
VmHostFileVO).

---

Nitpick comments:
In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Around line 339-386: Add a short, clear comment in KvmTpmManager describing
that the "send-delete-commands-to-hosts" flow performs best-effort cleanup: when
KvmCommandSender.send(...) for WriteVmHostFileContentCmd fails the code
intentionally logs a warning in the ReturnValueCompletion.fail(...) block and
continues DB cleanup; place the comment either at the start of the
Flow.of("send-delete-commands-to-hosts") block or immediately above the
fail(...) handler to document that failures are non-fatal and expected behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d1a84fec-1771-4dac-a9f4-efc186c3c56b

📥 Commits

Reviewing files that changed from the base of the PR and between 8663f8b and efc4fc2.

📒 Files selected for processing (1)
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java

@zstack-robot-2 zstack-robot-2 deleted the sync/wenhao.zhang/zsv-ldap-4 branch April 2, 2026 15:55
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