Skip to content

<fix>[kvm]: detach resource key from VmHostBackupFileVO when remove TpmVO#3885

Closed
ZStack-Robot wants to merge 1 commit into
zsv_5.0.0from
sync/wenhao.zhang/c-4
Closed

<fix>[kvm]: detach resource key from VmHostBackupFileVO when remove TpmVO#3885
ZStack-Robot wants to merge 1 commit into
zsv_5.0.0from
sync/wenhao.zhang/c-4

Conversation

@ZStack-Robot

Copy link
Copy Markdown
Collaborator

Resolves: ZSV-11845

Change-Id: I6f6e707368797a796662736d68666d62697a796f

sync from gitlab !9765

@coderabbitai

coderabbitai Bot commented Apr 29, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

将 TPM 分离/重置的残留清理改为基于 CloudBus 消息的两阶段流程:在 reset 路径先发送非强制的 VmHostFileDeletionMsg 删除最后主机文件并仅在成功后继续;随后枚举 VM 的 TPM-state 备份 UUID,针对每个 UUID 调用 tpmKeyBackend.cleanEncryptedResourceKey(...) 清理加密资源密钥,并通过带 forceDelete=trueVmHostFileDeletionMsg 强制删除备份,聚合并记录每个备份删除/清理失败后继续链式处理。removeTpmFromVm 在解绑 key-provider 后也会枚举并清理备份的加密资源密钥。

Changes

Cohort / File(s) Summary
TPM 清理与重置流程
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
替换原先直接 SQLBatch 删除为 CloudBus 消息驱动:在 resetVmTpm 先发送 VmHostFileDeletionMsg(..., forceDelete=false) 删除最后主机文件并仅在回复成功时继续;之后列举 VM 的 TPM-state 备份 UUID,逐个调用 tpmKeyBackend.cleanEncryptedResourceKey(...) 清理加密资源密钥,并对每个 UUID 发送 VmHostFileDeletionMsg(..., forceDelete=true) 强制删除备份;收集每个备份的错误并记录警告,但继续后续链式步骤。removeTpmFromVm 在 key-provider 解绑定后也列举并清理对应备份密钥。
备份文件清理日志增强
plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java
clean() 调用 resourceKeyBackend.cleanEncryptedResourceKey(...) 前增加调试日志,打印将要处理的 VmHostBackupFileVO UUID,随后执行原有清理逻辑并调用父类 super.clean()

Sequence Diagram(s)

sequenceDiagram
    participant Manager as KvmTpmManager
    participant SecureBoot as SecureBootService
    participant KeyBackend as tpmKeyBackend
    participant DB as BackupStore

    Manager->>SecureBoot: VmHostFileDeletionMsg(lastHostFileUuid, forceDelete=false)
    SecureBoot-->>Manager: reply (success / error)

    alt host-file deletion 成功
        Manager->>DB: list TPM-state backup UUIDs for VM
        DB-->>Manager: [uuid1, uuid2, ...] or []
        alt 有备份
            loop 对每个 uuid
                Manager->>KeyBackend: cleanEncryptedResourceKey(uuid)
                KeyBackend-->>Manager: success / failure
                Manager->>SecureBoot: VmHostFileDeletionMsg(uuid, forceDelete=true)
                SecureBoot-->>Manager: success / error
                Note over Manager: 聚合并记录失败,继续下一个 UUID
            end
        else 无备份
            Note over Manager: 跳过备份清理阶段
        end
    else host-file deletion 失败
        Note over Manager: 记录错误并失败退出该步骤
    end

    Manager->>Manager: 继续后续链式步骤
Loading

代码审查工作量评估

🎯 4 (Complex) | ⏱️ ~45 minutes

诗歌

🐰 我绕着 UUID 跳一圈,
请安全启动先把主文件扔远,
再把密钥一一轻声扫,
若有差错我会记下痕,
链式继续,不回头看。

🚥 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 标题清晰指出了主要变更:从删除TpmVO时从VmHostBackupFileVO中分离资源密钥,与代码变更内容相符。
Description check ✅ Passed 描述虽然简洁,但明确关联到问题跟踪号ZSV-11845和gitlab同步来源,与代码变更相关。
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/wenhao.zhang/c-4

Review rate limit: 2/5 reviews remaining, refill in 29 minutes and 8 seconds.

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.

Actionable comments posted: 1

Caution

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

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

799-850: ⚠️ Potential issue | 🔴 Critical

严重问题:SQLBatch 会在异步 While 循环完成前执行,导致竞态条件。

第 837-849 行的 SQLBatchtrigger.next() 位于 While...run() 调用之后但在 WhileDoneCompletion 回调之外。由于 While 是异步执行的,这些代码会在备份文件删除消息处理完成之前立即执行,导致:

  1. 数据库记录可能在 VmHostBackupFileDeletionMsg 消息处理之前就被删除
  2. TpmStateVmHostBackupFileBase.clean() 中的 cleanEncryptedResourceKey 可能无法正确执行

正确的做法是将 SQLBatch 移到 WhileDoneCompletion 回调内部。

🐛 建议的修复
                     }).run(new WhileDoneCompletion(trigger) {
                         `@Override`
                         public void done(ErrorCodeList errorCodeList) {
                             if (errorCodeList.hasError()) {
                                 String details = String.join("\n", transform(errorCodeList.getCauses(), ErrorCode::getReadableDetails));
                                 logger.warn("failed to clean backup files but still continue:\n" + details);
                             }
-                            trigger.next();
-                        }
-                    });
-
-                    new SQLBatch() {
-                        `@Override`
-                        protected void scripts() {
-                            sql(VmHostFileVO.class)
-                                    .eq(VmHostFileVO_.uuid, context.hostFileToDeleteLast.getUuid())
-                                    .delete();
-                            sql(VmHostBackupFileVO.class)
-                                    .eq(VmHostBackupFileVO_.resourceUuid, vmUuid)
-                                    .eq(VmHostBackupFileVO_.type, VmHostFileType.TpmState)
-                                    .delete();
+                            new SQLBatch() {
+                                `@Override`
+                                protected void scripts() {
+                                    sql(VmHostFileVO.class)
+                                            .eq(VmHostFileVO_.uuid, context.hostFileToDeleteLast.getUuid())
+                                            .delete();
+                                    sql(VmHostBackupFileVO.class)
+                                            .eq(VmHostBackupFileVO_.resourceUuid, vmUuid)
+                                            .eq(VmHostBackupFileVO_.type, VmHostFileType.TpmState)
+                                            .delete();
+                                }
+                            }.execute();
+                            trigger.next();
                         }
-                    }.execute();
-                    trigger.next();
+                    });
                 })
                 .build())
🤖 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
799 - 850, The SQLBatch that deletes VmHostFileVO and VmHostBackupFileVO runs
immediately after While.run(), causing a race because the asynchronous While
(sending VmHostBackupFileDeletionMsg) may not have finished; move the SQLBatch
execution and the trigger.next() call into the WhileDoneCompletion.done(...)
callback so the DB deletes occur only after the WhileDoneCompletion finishes
processing errors; specifically, relocate the SQLBatch block and the
trigger.next() currently after While.run() into the done(ErrorCodeList) method
(after handling errorCodeList) to ensure VmHostBackupFileDeletionMsg handling
(and cleanEncryptedResourceKey in TpmStateVmHostBackupFileBase) completes before
removing records tied to context.hostFileToDeleteLast, VmHostFileVO, and
VmHostBackupFileVO.
🧹 Nitpick comments (1)
plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java (1)

89-94: 日志级别可能过高。

logger.warn() 通常用于警告或异常情况,但根据上下文,这只是 TPM 移除时的常规清理操作。建议改为 logger.debug()logger.info(),与该文件中其他日志保持一致(参见第 41、47、58、65、71 行)。

此外,日志格式建议统一使用 uuid:%s 而非 uuid=%s,与同文件其他日志保持风格一致。

♻️ 建议的修改
 `@Override`
 public void clean() {
-    logger.warn(String.format("clean TpmState VmBackupFileVO[uuid=%s]", self.getUuid()));
+    logger.debug(String.format("clean TpmState VmBackupFileVO[uuid:%s]", self.getUuid()));
     resourceKeyBackend.cleanEncryptedResourceKey(self.getUuid());
     super.clean();
 }
🤖 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/TpmStateVmHostBackupFileBase.java`
around lines 89 - 94, In TpmStateVmHostBackupFileBase.clean(), lower the log
level from logger.warn to logger.info (or logger.debug for verbose) and change
the message format to match the file style by using "uuid:%s" instead of
"uuid=%s"; keep the calls to
resourceKeyBackend.cleanEncryptedResourceKey(self.getUuid()) and super.clean()
unchanged so only the logger invocation (in method clean) is adjusted for
consistency with other logs in this class.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Around line 461-474: The loop in KvmTpmManager's flow uses a raw for-loop to
call tpmKeyBackend.cleanEncryptedResourceKey for each backupUuid, lacking the
fault-tolerant behavior used in KvmSecureBootManager; replace the for-loop with
CollectionUtils.safeForEach(backupUuidList,
tpmKeyBackend::cleanEncryptedResourceKey) so failures cleaning one
VmHostBackupFileVO backupUuid won't abort the flow, keeping the detach step
(tpmKeyBackend.detachKeyProviderFromTpm with context.tpmUuid) and the query that
builds backupUuidList (Q.New on VmHostBackupFileVO /
VmHostBackupFileVO_.resourceUuid and VmHostBackupFileVO_.type using
context.vmInstanceUuid and VmHostFileType.TpmState) intact.

---

Outside diff comments:
In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Around line 799-850: The SQLBatch that deletes VmHostFileVO and
VmHostBackupFileVO runs immediately after While.run(), causing a race because
the asynchronous While (sending VmHostBackupFileDeletionMsg) may not have
finished; move the SQLBatch execution and the trigger.next() call into the
WhileDoneCompletion.done(...) callback so the DB deletes occur only after the
WhileDoneCompletion finishes processing errors; specifically, relocate the
SQLBatch block and the trigger.next() currently after While.run() into the
done(ErrorCodeList) method (after handling errorCodeList) to ensure
VmHostBackupFileDeletionMsg handling (and cleanEncryptedResourceKey in
TpmStateVmHostBackupFileBase) completes before removing records tied to
context.hostFileToDeleteLast, VmHostFileVO, and VmHostBackupFileVO.

---

Nitpick comments:
In
`@plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java`:
- Around line 89-94: In TpmStateVmHostBackupFileBase.clean(), lower the log
level from logger.warn to logger.info (or logger.debug for verbose) and change
the message format to match the file style by using "uuid:%s" instead of
"uuid=%s"; keep the calls to
resourceKeyBackend.cleanEncryptedResourceKey(self.getUuid()) and super.clean()
unchanged so only the logger invocation (in method clean) is adjusted for
consistency with other logs in this class.
🪄 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: c88b2313-11e5-4f44-991d-677ef0f94669

📥 Commits

Reviewing files that changed from the base of the PR and between 7df51d6 and db04a1a.

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

Comment on lines 461 to 474
.then(Flow.of("detach-resource-key")
.handle(trigger -> {
tpmKeyBackend.detachKeyProviderFromTpm(context.tpmUuid);
List<String> backupUuidList = Q.New(VmHostBackupFileVO.class)
.eq(VmHostBackupFileVO_.resourceUuid, context.vmInstanceUuid)
.eq(VmHostBackupFileVO_.type, VmHostFileType.TpmState)
.select(VmHostBackupFileVO_.uuid)
.listValues();
for (String backupUuid : backupUuidList) {
tpmKeyBackend.cleanEncryptedResourceKey(backupUuid);
}
trigger.next();
})
.build())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 检查 cleanEncryptedResourceKey 的实现,确认其异常处理行为
ast-grep --pattern $'void cleanEncryptedResourceKey($$$) {
  $$$
}'

Repository: MatheMatrix/zstack

Length of output: 44


🏁 Script executed:

rg -t java "cleanEncryptedResourceKey" --max-count 20

Repository: MatheMatrix/zstack

Length of output: 999


🏁 Script executed:

fd -t f -name "*.java" | xargs rg "interface.*TpmEncryptedResourceKeyBackend|class.*TpmEncryptedResourceKeyBackend" -l

Repository: MatheMatrix/zstack

Length of output: 535


🏁 Script executed:

fd -t f -name "*.java" -path "*tpm*" | head -20

Repository: MatheMatrix/zstack

Length of output: 293


🏁 Script executed:

cat -n compute/src/main/java/org/zstack/compute/vm/devices/TpmEncryptedResourceKeyBackend.java

Repository: MatheMatrix/zstack

Length of output: 3594


🏁 Script executed:

cat -n compute/src/main/java/org/zstack/compute/vm/devices/DummyTpmEncryptedResourceKeyBackend.java

Repository: MatheMatrix/zstack

Length of output: 2982


🏁 Script executed:

rg -A 10 "safeForEach.*cleanEncryptedResourceKey" plugin/kvm/src/main/java/org/zstack/kvm/efi/KvmSecureBootManager.java

Repository: MatheMatrix/zstack

Length of output: 1165


🏁 Script executed:

cat -n plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java | grep -A 5 -B 5 "cleanEncryptedResourceKey"

Repository: MatheMatrix/zstack

Length of output: 367


🏁 Script executed:

rg -t java "class.*implements.*TpmEncryptedResourceKeyBackend" --max-count 10

Repository: MatheMatrix/zstack

Length of output: 248


🏁 Script executed:

rg -A 20 "public void cleanEncryptedResourceKey" plugin/kvm/src/main/java/org/zstack/kvm/tpm/ -t java

Repository: MatheMatrix/zstack

Length of output: 44


🏁 Script executed:

rg "safeForEach" plugin/kvm/src/main/java/org/zstack/kvm/efi/KvmSecureBootManager.java -B 5 -A 5

Repository: MatheMatrix/zstack

Length of output: 995


🏁 Script executed:

rg -t java "void safeForEach" --max-count 5

Repository: MatheMatrix/zstack

Length of output: 206


🏁 Script executed:

rg -B 10 -A 10 "safeForEach" plugin/kvm/src/main/java/org/zstack/kvm/efi/KvmSecureBootManager.java | head -40

Repository: MatheMatrix/zstack

Length of output: 2111


🏁 Script executed:

find plugin/kvm/src/main/java/org/zstack/kvm/tpm -name "*.java" -exec grep -l "implements TpmEncryptedResourceKeyBackend" {} \;

Repository: MatheMatrix/zstack

Length of output: 44


🏁 Script executed:

cat -n utils/src/main/java/org/zstack/utils/CollectionUtils.java | grep -A 15 "void safeForEach"

Repository: MatheMatrix/zstack

Length of output: 766


🏁 Script executed:

rg -A 5 "interface ForEachFunction" utils/src/main/java/org/zstack/utils/CollectionUtils.java

Repository: MatheMatrix/zstack

Length of output: 44


🏁 Script executed:

rg -t java "public void cleanEncryptedResourceKey" compute/ plugin/ -A 5

Repository: MatheMatrix/zstack

Length of output: 749


🏁 Script executed:

cat -n plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java | sed -n '461,475p'

Repository: MatheMatrix/zstack

Length of output: 980


🏁 Script executed:

rg "class KvmTpmManager" plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java -A 1

Repository: MatheMatrix/zstack

Length of output: 195


应该使用 safeForEach() 以保持与 KvmSecureBootManager 一致的容错处理。

KvmSecureBootManager 中,对 cleanEncryptedResourceKey() 的调用使用 safeForEach() 进行包装,该工具方法会捕获所有异常并继续执行,符合 ZStack 的 best-effort 处理模式。但在 KvmTpmManager 的这个流程中(469-470 行)使用了原始 for 循环,缺少同样的容错保护。

建议改为:

CollectionUtils.safeForEach(backupUuidList, tpmKeyBackend::cleanEncryptedResourceKey);

这样可以保证即使某个备份文件的密钥清理失败,也不会中断整个流程。

🤖 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
461 - 474, The loop in KvmTpmManager's flow uses a raw for-loop to call
tpmKeyBackend.cleanEncryptedResourceKey for each backupUuid, lacking the
fault-tolerant behavior used in KvmSecureBootManager; replace the for-loop with
CollectionUtils.safeForEach(backupUuidList,
tpmKeyBackend::cleanEncryptedResourceKey) so failures cleaning one
VmHostBackupFileVO backupUuid won't abort the flow, keeping the detach step
(tpmKeyBackend.detachKeyProviderFromTpm with context.tpmUuid) and the query that
builds backupUuidList (Q.New on VmHostBackupFileVO /
VmHostBackupFileVO_.resourceUuid and VmHostBackupFileVO_.type using
context.vmInstanceUuid and VmHostFileType.TpmState) intact.

@zstack-robot-2

Copy link
Copy Markdown
Collaborator

Comment from yaohua.wu:

Review: MR !9765 — ZSV-11845

结论:REVISION_REQUIRED — 修复方向正确(在 TPM 删除/重置链路上补齐 EncryptedResourceKeyRefVO 清理),但 remove-backups-db-records-for-remains 这一步把"异步消息派发 + 同步 SQLBatch + 同步 trigger.next()"硬糅在同一个 handle,会造成 trigger 双触发与消息/SQL 抢跑,必须在合入前修掉。

🔴 Critical

1. remove-backups-db-records-for-remains 同时存在异步与同步两条 trigger.next() 路径,且 SQLBatch 会抢在 DeletionMsg 之前执行 — KvmTpmManager.java ~L795-L832(resetVmTpm

完整 handle 体如下:

.handle(trigger -> {
    List<String> backupUuidList = Q.New(VmHostBackupFileVO.class)
            .eq(VmHostBackupFileVO_.resourceUuid, vmUuid)
            .eq(VmHostBackupFileVO_.type, VmHostFileType.TpmState)
            .select(VmHostBackupFileVO_.uuid)
            .listValues();
    if (isEmpty(backupUuidList)) {
        trigger.next();
        return;
    }

    new While<>(backupUuidList).each((uuid, whileCompletion) -> {
        VmHostBackupFileDeletionMsg deletionMsg = new VmHostBackupFileDeletionMsg();
        deletionMsg.setUuid(uuid);
        deletionMsg.setForceDelete(true);
        bus.makeLocalServiceId(deletionMsg, VmInstanceConstant.SECURE_BOOT_SERVICE_ID);
        bus.send(deletionMsg, new CloudBusCallBack(whileCompletion) { ... });
    }).run(new WhileDoneCompletion(trigger) {
        @Override public void done(ErrorCodeList errorCodeList) {
            ...
            trigger.next();        // ← 异步路径
        }
    });

    new SQLBatch() {                // ← 同步立即执行
        @Override protected void scripts() {
            sql(VmHostFileVO.class)
                    .eq(VmHostFileVO_.uuid, context.hostFileToDeleteLast.getUuid())
                    .delete();
            sql(VmHostBackupFileVO.class)
                    .eq(VmHostBackupFileVO_.resourceUuid, vmUuid)
                    .eq(VmHostBackupFileVO_.type, VmHostFileType.TpmState)
                    .delete();
        }
    }.execute();
    trigger.next();                 // ← 同步路径,与上面 WhileDoneCompletion 重复
})

非空 backupUuidList 路径下会出现两个独立问题,根因都是这次"由 SQL.delete 改为 DeletionMsg"的迁移没做完整:

  • trigger 双触发While.run(...) 拿到 trigger 异步派发,最终在 WhileDoneCompletion.done()trigger.next();与此同时 handle 末尾还残留一条同步的 trigger.next();。两条都会真实触发,下一个 step delete-host-secret 大概率会被跑两次(轻则重复删 host secret 报 warn,重则 chain 状态错乱)。

  • SQLBatch 抢跑、绕过 TpmStateVmHostBackupFileBase.clean()new While<>(...).run(...) 仅完成派发就返回,bus.send 尚未让消息处理端跑到 TpmStateVmHostBackupFileBase.clean() → resourceKeyBackend.cleanEncryptedResourceKey(self.getUuid()) → super.clean()。紧跟着的 new SQLBatch().execute() 已经同步把 VmHostBackupFileVO 行直接删除,等消息侧再去 lookup 时行已不存在,整个 DeletionMsg 路径形同虚设——既然这次 MR 的目标就是改走消息体系,这个 SQLBatch 必须删除。同样 sql(VmHostFileVO).eq(uuid=hostFileToDeleteLast.uuid).delete() 与上一个 step 派发的 VmHostFileDeletionMsg(forceDelete=false) 也是重复,前一步已经把这个 VO 删掉了。

    附带的"空 backup 早退"分支 (if (isEmpty(backupUuidList)) { trigger.next(); return; }) 顺带把 SQLBatch 也跳过——只是因为消息路径本来就把这两个 VO 都删完了所以表现为正确,但语义上是巧合而非设计。

修复建议(最小改动):

new While<>(backupUuidList).each(...).run(new WhileDoneCompletion(trigger) {
    @Override public void done(ErrorCodeList errorCodeList) {
        if (errorCodeList.hasError()) {
            String details = String.join("\n",
                    transform(errorCodeList.getCauses(), ErrorCode::getReadableDetails));
            logger.warn("failed to clean backup files but still continue:\n" + details);
        }
        trigger.next();
    }
});
// 删除下面整段 SQLBatch 与多余的 trigger.next()

即彻底删除 new SQLBatch() { ... }.execute(); 和它后面那条 trigger.next();,让 WhileDoneCompletion 成为唯一的 trigger 出口。验证一下 VmHostFileDeletionMsg(forceDelete=false)VmHostBackupFileDeletionMsg(forceDelete=true) 在各自 handler 里确实把对应 VO 行删掉就行(按 !9755 / premium !13699 的方向,应当如此)。

🟡 Warning

2. EncryptedResourceKey 在同一个流程里被清理两次 — KvmTpmManager.java L460-L471 与 TpmStateVmHostBackupFileBase.java L91

detach-resource-key 已经显式:

List<String> backupUuidList = Q.New(VmHostBackupFileVO.class)
        .eq(VmHostBackupFileVO_.resourceUuid, context.vmInstanceUuid)
        .eq(VmHostBackupFileVO_.type, VmHostFileType.TpmState)
        .select(VmHostBackupFileVO_.uuid)
        .listValues();
for (String backupUuid : backupUuidList) {
    tpmKeyBackend.cleanEncryptedResourceKey(backupUuid);
}

而后续走 VmHostBackupFileDeletionMsgTpmStateVmHostBackupFileBase.clean() 又会再清一次:

public void clean() {
    logger.warn(...);
    resourceKeyBackend.cleanEncryptedResourceKey(self.getUuid());
    super.clean();
}

如果 cleanEncryptedResourceKey 只是删 EncryptedResourceKeyRefVO 行,这次只是日志噪声;但若内部对接 NKP/KMS 远程撤销,这种"对一把已不存在的 key 再撤销一次"会刷出告警或 4xx。建议二选一:要么在 detach-resource-key 阶段只 detach key provider,把 backup 的 key 清理交给 deletion 消息链路;要么 clean() 内部增加幂等判断。从职责切分上推荐前者。

注意:这条与 Critical #1 是耦合的——SQLBatch 一删,删除路径就只剩消息一条线,clean() 必然会被调,重复调用问题就暴露出来了。

3. logger.warn 用错级别 — TpmStateVmHostBackupFileBase.java L91

logger.warn(String.format("clean TpmState VmBackupFileVO[uuid=%s]", self.getUuid()));

clean() 是正常删除路径,不是异常情况。warn 级别会污染告警日志、在监控里制造误报噪声。改成 logger.infologger.debug

4. 通配符 import — KvmTpmManager.java L46

import org.zstack.header.vm.additions.*;

原本 8 条显式 import 被合成一条通配符。zstack 代码库一致使用显式 import,建议保留显式列表(仅新增 VmHostBackupFileDeletionMsgVmHostFileDeletionMsg 即可)。

5. 验证不充分,长青脚本未跑过

ZSV-11845 在 4/15 与 4/26 反复出现"还有场景遗漏"。Jira 评论里张鹏翊 4/23 给出了完整 7 步 CLI 长青脚本(创建 nkp1 → vm1/vm2 各种快照/备份/模板 → 删 nkp1 → 各种克隆 → 彻底删除 → 创建 nkp2 → 全局 rekey 应零脏数据),4/29 又给了清理残留数据的 SQL。本 MR 没有附带任何自动化 case,premium 侧 !13707 / !13708 已经把 Tpm/EncryptedResourceKeyRefVO 的 clean 放开,恰好可以把这条长青补成 zsv-system-test:

  • delete VM → 全局 rekey 零脏数据
  • reset TPM → 同上
  • 各种从 backup/snapshot/template 创建链路下的失败回滚
  • 自测里挂着的"从 OVF 创建失败回滚"

合入前请至少在测试环境(如 ZSV-11845 评论里那台 172.24.251.247)人工跑完一遍并把结果贴回 issue。

6. removeTpmFromVmresetVmTpm 在 backup 清理路径上风格不一致 — KvmTpmManager.java L478-L500(删除路径)

resetVmTpm 改用了 DeletionMsg,但 removeTpmFromVm(即 TpmDeletionMsg 的处理)依旧是裸 sql(VmHostBackupFileVO)...delete()

.then(Flow.of("remove-db-records")
    .handle(trigger -> {
        new SQLBatch() {
            @Override protected void scripts() {
                sql(TpmVO.class).eq(TpmVO_.uuid, context.tpmUuid).delete();
                sql(VmHostFileVO.class).eq(VmHostFileVO_.vmInstanceUuid, ...).delete();
                sql(VmHostBackupFileVO.class).eq(VmHostBackupFileVO_.resourceUuid, ...).delete();
            }
        }.execute();
        trigger.next();
    })

按 ZSV-11845 4/28 wenhao.zhang 的整体方向("大量清理 SQL.delete 原生调用,改用 cascade 和 VmHostFileDeletionMsg 体系"),删除路径理应一并迁移;这里继续用 SQL.delete 等于绕过 TpmStateVmHostBackupFileBase.clean(),未来如果 clean() 里加了别的语义(例如清磁盘文件、推消息),删除路径就会再次成为遗漏点。

如果本次范围有限不打算改,请至少在 PR 描述里挂一个跟进 issue/MR,避免下一次又重蹈"还有场景遗漏"。

🟢 Suggestion

7. 注释表达可读性 — KvmTpmManager.java ~L815

deletionMsg.setForceDelete(true); // set true when VmHostFileVO deleted

读起来像"当 VmHostFileVO 被删除时设为 true"。建议改成:// VmHostFileVO has been deleted in the previous step, so force delete here is safe

8. detach-resource-key 步骤职责膨胀

现在它既 detach TPM key provider,又遍历清理所有 TpmState backup 的 EncryptedResourceKey。建议拆成两个 step(如 detach-resource-key + cleanup-backup-encrypted-keys),与 Warning #2 的去重一并收敛会更干净。

兼容性 / Upstream Freshness

  • merge_status: can_be_mergeddiverged_commits_count: 0、目标分支 zsv_5.0.0 当前无冲突,无需 rebase。
  • 与 ZSV-11845 4/28 整体方案一致(!9751 / !9755 / premium !13699 / premium !13664 + 本 MR 是补 TPM 删除时遗漏的 EncryptedResourceKey 清理这一块),定位准确。

Verdict

REVISION_REQUIRED — Critical #1 必须修;建议同时把 Warning #2#3#4 一并收敛,并补一次完整长青验证(Warning #5)后再合入。


🤖 Robot Reviewer

@MatheMatrix MatheMatrix force-pushed the sync/wenhao.zhang/c-4 branch from db04a1a to cb6591a Compare April 29, 2026 17:13

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

829-831: 建议将日志级别从 warn 调整为 infodebug

此处的清理失败是被预期并容忍的(代码继续执行),使用 logger.warn 级别可能导致运维告警噪音。根据 PR 评审意见 (Warning #3),建议改为 infodebug 级别。

♻️ 建议的修改
                         if (errorCodeList.hasError()) {
                             String details = String.join("\n", transform(errorCodeList.getCauses(), ErrorCode::getReadableDetails));
-                            logger.warn("failed to clean backup files but still continue:\n" + details);
+                            logger.info("failed to clean backup files but still continue:\n" + details);
                         }
🤖 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
829 - 831, The cleanup failure in KvmTpmManager is expected and tolerated, so
change the logging level from logger.warn to a lower level (logger.info or
logger.debug) in the block that checks errorCodeList.hasError(); specifically
update the call that currently logs "failed to clean backup files but still
continue:\n" + details (constructed from transform(errorCodeList.getCauses(),
ErrorCode::getReadableDetails)) to use logger.info or logger.debug so it doesn’t
generate unnecessary alerts.

815-815: 建议完善注释说明。

当前注释 // set true when VmHostFileVO deleted 较为简略。建议补充说明:由于父级 VmHostFileVO 已在上一步被删除,备份文件的清理失败应被容忍以避免残留数据。

📝 建议的注释
-                        deletionMsg.setForceDelete(true); // set true when VmHostFileVO deleted
+                        // Parent VmHostFileVO was already deleted; tolerate cleanup failures to avoid orphan data
+                        deletionMsg.setForceDelete(true);
🤖 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` at line 815,
在 KvmTpmManager.java 中补充 deletionMsg.setForceDelete(true) 的注释,说明为什么在
VmHostFileVO 已被删除的情况下要将 forceDelete 设为 true:由于父对象 VmHostFileVO
在前一步已被删除,后续对备份/主机文件的删除操作即便失败也应被容忍以避免留下未预期的数据或阻塞流程;请在
deletionMsg.setForceDelete(true) 旁加入一条清晰注释,引用
VmHostFileVO、deletionMsg.setForceDelete(true) 和相关上下文以便维护者理解其原因和意图。

48-48: 建议使用显式导入替代通配符导入。

通配符导入 org.zstack.header.vm.additions.* 不符合代码库的一致性要求。根据 PR 评审意见 (Warning #4),应使用显式导入以保持与其他代码的风格一致。

♻️ 建议的修改
-import org.zstack.header.vm.additions.*;
+import org.zstack.header.vm.additions.VmHostBackupFileDeletionMsg;
+import org.zstack.header.vm.additions.VmHostBackupFileVO;
+import org.zstack.header.vm.additions.VmHostBackupFileVO_;
+import org.zstack.header.vm.additions.VmHostFileDeletionMsg;
+import org.zstack.header.vm.additions.VmHostFileInventory;
+import org.zstack.header.vm.additions.VmHostFileOperation;
+import org.zstack.header.vm.additions.VmHostFileType;
+import org.zstack.header.vm.additions.VmHostFileVO;
+import org.zstack.header.vm.additions.VmHostFileVO_;
🤖 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` at line 48,
当前文件在 KvmTpmManager.java 中使用了通配符导入
org.zstack.header.vm.additions.*;请将该通配符替换为对本文件实际使用到的每个具体类型的显式导入(在 KvmTpmManager
类中查找使用的类型名并为每个添加单独的 import 语句),确保删除 org.zstack.header.vm.additions.*
并仅保留具体类的导入以符合项目风格一致性要求。
🤖 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 829-831: The cleanup failure in KvmTpmManager is expected and
tolerated, so change the logging level from logger.warn to a lower level
(logger.info or logger.debug) in the block that checks errorCodeList.hasError();
specifically update the call that currently logs "failed to clean backup files
but still continue:\n" + details (constructed from
transform(errorCodeList.getCauses(), ErrorCode::getReadableDetails)) to use
logger.info or logger.debug so it doesn’t generate unnecessary alerts.
- Line 815: 在 KvmTpmManager.java 中补充 deletionMsg.setForceDelete(true) 的注释,说明为什么在
VmHostFileVO 已被删除的情况下要将 forceDelete 设为 true:由于父对象 VmHostFileVO
在前一步已被删除,后续对备份/主机文件的删除操作即便失败也应被容忍以避免留下未预期的数据或阻塞流程;请在
deletionMsg.setForceDelete(true) 旁加入一条清晰注释,引用
VmHostFileVO、deletionMsg.setForceDelete(true) 和相关上下文以便维护者理解其原因和意图。
- Line 48: 当前文件在 KvmTpmManager.java 中使用了通配符导入
org.zstack.header.vm.additions.*;请将该通配符替换为对本文件实际使用到的每个具体类型的显式导入(在 KvmTpmManager
类中查找使用的类型名并为每个添加单独的 import 语句),确保删除 org.zstack.header.vm.additions.*
并仅保留具体类的导入以符合项目风格一致性要求。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 991b4222-9f2c-424e-8748-707282934bc2

📥 Commits

Reviewing files that changed from the base of the PR and between db04a1a and cb6591a.

📒 Files selected for processing (2)
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java

@MatheMatrix MatheMatrix force-pushed the sync/wenhao.zhang/c-4 branch from cb6591a to 4a8bc62 Compare April 29, 2026 17:22

@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.

♻️ Duplicate comments (1)
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java (1)

461-470: ⚠️ Potential issue | 🟠 Major

这里的备份密钥清理不应该让删 TPM 流程中途失败。

这和上一轮在同一段提到的问题一致:detachKeyProviderFromTpm() 已经先执行了,如果某个 cleanEncryptedResourceKey(backupUuid) 抛异常,后面的 remove-db-records 就不会执行,最终会留下“provider 已解绑,但 TPM / 备份记录还在”的半清理状态。这里更适合做成 best-effort,逐个记录失败并继续。

♻️ 建议修改
-                    for (String backupUuid : backupUuidList) {
-                        tpmKeyBackend.cleanEncryptedResourceKey(backupUuid);
-                    }
+                    CollectionUtils.safeForEach(backupUuidList, tpmKeyBackend::cleanEncryptedResourceKey);
🤖 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
461 - 470, 在 detach-resource-key 的处理器里,cleanEncryptedResourceKey(backupUuid)
不能让整个流程因单个备份失败而中断:把对 tpmKeyBackend.cleanEncryptedResourceKey 的调用改为对每个 backupUuid
分别做 best-effort(在循环内用 try/catch 捕获异常并记录错误,继续下一个),确保
detachKeyProviderFromTpm(context.tpmUuid) 已执行后即便某些清理失败也不会阻止后续的 remove-db-records
或后续流程运行;引用符号:detachKeyProviderFromTpm, cleanEncryptedResourceKey,
context.vmInstanceUuid, Flow.of("detach-resource-key")。
🧹 Nitpick comments (1)
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java (1)

48-48: 避免新增通配符导入。

这里实际只新增了少量 vm.additions 类型,继续使用 org.zstack.header.vm.additions.* 会让依赖面不透明,也和本类其余导入的显式风格不一致,建议改回按需导入。

🤖 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` at line 48,
Replace the wildcard import "org.zstack.header.vm.additions.*" in
KvmTpmManager.java with explicit imports: remove the star import and add
individual import statements for each class from org.zstack.header.vm.additions
that this file actually uses (identify those types by scanning
KvmTpmManager.java for references to classes from that package and import them
explicitly). Keep the rest of the file's import style consistent and ensure no
unused imports remain.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Around line 461-470: 在 detach-resource-key
的处理器里,cleanEncryptedResourceKey(backupUuid) 不能让整个流程因单个备份失败而中断:把对
tpmKeyBackend.cleanEncryptedResourceKey 的调用改为对每个 backupUuid 分别做
best-effort(在循环内用 try/catch 捕获异常并记录错误,继续下一个),确保
detachKeyProviderFromTpm(context.tpmUuid) 已执行后即便某些清理失败也不会阻止后续的 remove-db-records
或后续流程运行;引用符号:detachKeyProviderFromTpm, cleanEncryptedResourceKey,
context.vmInstanceUuid, Flow.of("detach-resource-key")。

---

Nitpick comments:
In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Line 48: Replace the wildcard import "org.zstack.header.vm.additions.*" in
KvmTpmManager.java with explicit imports: remove the star import and add
individual import statements for each class from org.zstack.header.vm.additions
that this file actually uses (identify those types by scanning
KvmTpmManager.java for references to classes from that package and import them
explicitly). Keep the rest of the file's import style consistent and ensure no
unused imports remain.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: aee8e04b-9cb1-4ab3-9901-322e5e896d2b

📥 Commits

Reviewing files that changed from the base of the PR and between cb6591a and 4a8bc62.

📒 Files selected for processing (2)
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java

@MatheMatrix MatheMatrix force-pushed the sync/wenhao.zhang/c-4 branch from 4a8bc62 to 97f95b6 Compare April 29, 2026 17:36

@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

♻️ Duplicate comments (1)
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java (1)

479-481: ⚠️ Potential issue | 🟠 Major

备份密钥清理应改为容错继续,避免单点失败中断整条 TPM 删除链路。

这里逐个直接调用 tpmKeyBackend.cleanEncryptedResourceKey(backupUuid),任一异常都可能导致后续 remove-db-records 不执行,产生“部分清理”状态。建议改为 best-effort(不中断主流程)并记录失败。

建议修改
-                    for (String backupUuid : backupUuidList) {
-                        tpmKeyBackend.cleanEncryptedResourceKey(backupUuid);
-                    }
+                    CollectionUtils.safeForEach(backupUuidList, backupUuid -> {
+                        try {
+                            tpmKeyBackend.cleanEncryptedResourceKey(backupUuid);
+                        } catch (Exception e) {
+                            logger.warn(String.format("failed to clean encrypted key for backup[uuid:%s], continue tpm removal", backupUuid), e);
+                        }
+                    });

Based on learnings: In ZStack, calls to VmInstanceResourceMetadataManager.deleteVmResourceMetadata(...) commonly treat failures as best‑effort and do not block the primary operation.

🤖 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
479 - 481, The loop in KvmTpmManager that calls
tpmKeyBackend.cleanEncryptedResourceKey(backupUuid) must be made best‑effort:
wrap each call in a try/catch so a thrown exception is logged (including
backupUuid and exception details) but not rethrown, allowing the loop to
continue and the subsequent remove-db-records step to run; optionally
collect/log aggregate failures after the loop for visibility but do not abort
the TPM delete flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Around line 810-811: In KvmTpmManager remove the premature branch skip that
checks `.skipIf(data -> context.hostFileToDeleteLast == null)` so backup-file
deletion does not get skipped when only backup remnants (VmHostBackupFileVO)
exist; instead let the branch execute and let the existing
`isEmpty(backupUuidList)` early-return logic handle no-op cases; update the
pipeline where `.skipIf(data -> context.hostFileToDeleteLast == null)` appears
(and the similar block at the 812-820 region) to eliminate that skip and keep
the subsequent `.handle(trigger -> { ... isEmpty(backupUuidList) ... })`
behavior unchanged.

---

Duplicate comments:
In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Around line 479-481: The loop in KvmTpmManager that calls
tpmKeyBackend.cleanEncryptedResourceKey(backupUuid) must be made best‑effort:
wrap each call in a try/catch so a thrown exception is logged (including
backupUuid and exception details) but not rethrown, allowing the loop to
continue and the subsequent remove-db-records step to run; optionally
collect/log aggregate failures after the loop for visibility but do not abort
the TPM delete flow.
🪄 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: 9fc56e92-b35b-4515-81d1-a5052fb9352e

📥 Commits

Reviewing files that changed from the base of the PR and between 4a8bc62 and 97f95b6.

📒 Files selected for processing (2)
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java
✅ Files skipped from review due to trivial changes (1)
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java

Comment on lines +810 to +811
.skipIf(data -> context.hostFileToDeleteLast == null)
.handle(trigger -> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

备份删除不应依赖 hostFileToDeleteLast,否则会漏清理“仅备份残留”场景。

当前 .skipIf(data -> context.hostFileToDeleteLast == null) 会在没有 last host file 时直接跳过整个备份删除分支,但这时仍可能存在 VmHostBackupFileVO 残留。建议移除该 skip,继续用后面的 isEmpty(backupUuidList) 早退控制。

建议修改
             .then(Flow.of("remove-backups-db-records-for-remains")
-                .skipIf(data -> context.hostFileToDeleteLast == null)
                 .handle(trigger -> {
                     List<String> backupUuidList = Q.New(VmHostBackupFileVO.class)
                             .eq(VmHostBackupFileVO_.resourceUuid, vmUuid)
                             .eq(VmHostBackupFileVO_.type, VmHostFileType.TpmState)
                             .select(VmHostBackupFileVO_.uuid)
                             .listValues();

Also applies to: 812-820

🤖 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
810 - 811, In KvmTpmManager remove the premature branch skip that checks
`.skipIf(data -> context.hostFileToDeleteLast == null)` so backup-file deletion
does not get skipped when only backup remnants (VmHostBackupFileVO) exist;
instead let the branch execute and let the existing `isEmpty(backupUuidList)`
early-return logic handle no-op cases; update the pipeline where `.skipIf(data
-> context.hostFileToDeleteLast == null)` appears (and the similar block at the
812-820 region) to eliminate that skip and keep the subsequent `.handle(trigger
-> { ... isEmpty(backupUuidList) ... })` behavior unchanged.

…pmVO

Resolves: ZSV-11845

Change-Id: I6f6e707368797a796662736d68666d62697a796f
@MatheMatrix MatheMatrix force-pushed the sync/wenhao.zhang/c-4 branch from 97f95b6 to e3f138a Compare April 29, 2026 17:46

@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.

♻️ Duplicate comments (1)
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java (1)

474-481: ⚠️ Potential issue | 🟠 Major

单个备份 key 清理异常会中断整个 TPM 删除链。

这里是同步裸循环;只要某个 cleanEncryptedResourceKey() 抛异常,后面的 remove-db-records 就不会执行,最终会留下“已 detach 但未删库”的半清理状态。建议把这段改成逐个容错的 best-effort 处理,不要让单个 backup 失败阻塞主删除路径。

🤖 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
474 - 481, The loop in KvmTpmManager that iterates backupUuidList and calls
tpmKeyBackend.cleanEncryptedResourceKey(backupUuid) must be made best-effort
per-item: wrap each cleanEncryptedResourceKey call in its own try-catch, log the
failure (include backupUuid and exception) and continue so a single failure
doesn't abort the whole TPM delete path; ensure subsequent remove-db-records
logic that follows the loop still runs regardless of individual cleanup
failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Around line 474-481: The loop in KvmTpmManager that iterates backupUuidList
and calls tpmKeyBackend.cleanEncryptedResourceKey(backupUuid) must be made
best-effort per-item: wrap each cleanEncryptedResourceKey call in its own
try-catch, log the failure (include backupUuid and exception) and continue so a
single failure doesn't abort the whole TPM delete path; ensure subsequent
remove-db-records logic that follows the loop still runs regardless of
individual cleanup failures.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0ce9b742-bfc6-44d5-97d0-450c032c3a72

📥 Commits

Reviewing files that changed from the base of the PR and between 97f95b6 and e3f138a.

📒 Files selected for processing (2)
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java
✅ Files skipped from review due to trivial changes (1)
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmStateVmHostBackupFileBase.java

@ZStack-Robot ZStack-Robot deleted the sync/wenhao.zhang/c-4 branch April 30, 2026 00:30
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