Skip to content

<feature>[header]: Add TPM key backup for snapshot revert and rollback#3916

Closed
zstack-robot-1 wants to merge 1 commit intozsv_5.1.0from
sync/wenhao.zhang/zsv-8@@2
Closed

<feature>[header]: Add TPM key backup for snapshot revert and rollback#3916
zstack-robot-1 wants to merge 1 commit intozsv_5.1.0from
sync/wenhao.zhang/zsv-8@@2

Conversation

@zstack-robot-1
Copy link
Copy Markdown
Collaborator

Introduce internal TpmKeyBackupVO (no owner) to hold
the VM TPM encryption key during snapshot-group revert

Add DeleteTpmKeyBackupMsg / DeleteTpmKeyBackupReply
to remove the backup VO and its key ref.

Resolves: ZSV-12208
Related: ZSV-11310

Change-Id: I7a7967637667726a727666676a6162787277616e

sync from gitlab !9802

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

Review Change Stack

Walkthrough

此 PR 为 TPM 加密密钥恢复添加备份实体与消息,扩展后端接口与 KVM 管理器以支持备份-恢复-清理流程,并在快照组恢复工作流中记录与回滚/删除备份 UUID。

变更说明

TPM密钥备份与恢复流

层级 / 文件 说明
数据模型
header/src/main/java/org/zstack/header/tpm/entity/TpmKeyBackupVO.java, TpmKeyBackupVO_.java, conf/db/zsv/V5.1.0__schema.sql
新增 TpmKeyBackupVO JPA 实体及静态元模型,并添加建表 SQL。
消息协议扩展
header/src/main/java/org/zstack/header/tpm/message/RestoreTpmEncryptionKeyMsg.java, RestoreTpmEncryptionKeyReply.java
在恢复请求中增加 backupCurrentKey 标志(默认 true),在回复中返回 tpmKeyBackupUuid
删除消息类型
header/src/main/java/org/zstack/header/tpm/message/DeleteTpmKeyBackupMsg.java, DeleteTpmKeyBackupReply.java
新增用于删除备份记录与触发后端清理的消息对。
接口扩展
compute/src/main/java/org/zstack/compute/vm/devices/TpmEncryptedResourceKeyBackend.java
添加 cleanTpmKeyBackupEncryptedResourceKey(String tpmKeyBackupUuid) 方法声明用于清理备份相关加密材料。
虚拟实现
compute/src/main/java/org/zstack/compute/vm/devices/DummyTpmEncryptedResourceKeyBackend.java
在虚拟后端中实现该清理方法为 no-op,仅记录调试日志。
KVM TPM管理器
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
增加数据库与时间工具依赖注入,路由并处理 Delete 消息;在恢复流程中按条件创建并持久化 TpmKeyBackupVO、执行备份、返回备份 UUID;在异常时清理备份加密材料并删除 VO;实现删除备份处理器。
快照组工作流集成
storage/src/main/java/org/zstack/storage/snapshot/group/VolumeSnapshotGroupBase.java
在恢复上下文中记录 tpmKeyBackupUuid,恢复步骤请求备份并保存 UUID;添加回滚逻辑从备份恢复并删除临时备份;新增专用删除备份步骤以清理持久化状态。

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant KvmTpmManager
  participant DatabaseFacade
  participant TpmBackend
  Caller->>KvmTpmManager: RestoreTpmEncryptionKeyMsg(backupCurrentKey=true)
  KvmTpmManager->>DatabaseFacade: persist TpmKeyBackupVO (uuid)
  KvmTpmManager->>TpmBackend: backup current key -> store encrypted material under uuid
  TpmBackend-->>KvmTpmManager: backup OK
  KvmTpmManager->>TpmBackend: restore encrypted resource key from src
  TpmBackend-->>KvmTpmManager: restore OK
  KvmTpmManager-->>Caller: RestoreTpmEncryptionKeyReply(tpmKeyBackupUuid)
  Note over KvmTpmManager,DatabaseFacade: on Exception -> clean encrypted backup material, delete TpmKeyBackupVO
Loading

🎯 3 (Moderate) | ⏱️ ~25 分钟

🐰
备份一份小小钥
恢复若惊心惊跳
若错我会回滚退
清理记录不留骄

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.45% 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 The title clearly and concisely describes the main change: adding TPM key backup functionality for snapshot revert and rollback operations.
Description check ✅ Passed The description is directly related to the changeset, explaining the introduction of TpmKeyBackupVO and deletion messages for snapshot-group revert operations.
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/zsv-8@@2

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java`:
- Around line 698-706: In KvmTpmManager's catch(Throwable t) block, avoid
passing a possibly null t.getMessage() into reply.setError(operr(...)); instead
build a non-null error string (e.g. use t.getMessage() != null ? t.getMessage()
: t.toString() or include t.getClass().getName()) and pass that to operr,
keeping the existing cleanup calls to
tpmKeyBackend.cleanTpmKeyBackupEncryptedResourceKey(tpmKeyBackupUuid) and
databaseFacade.removeByPrimaryKey(tpmKeyBackupUuid, TpmKeyBackupVO.class) and
then reply.setTpmKeyBackupUuid(null); reply.setError(operr(...)); bus.reply(msg,
reply).

In
`@storage/src/main/java/org/zstack/storage/snapshot/group/VolumeSnapshotGroupBase.java`:
- Around line 595-614: The delete-tpm-key-backup flow in VolumeSnapshotGroupBase
currently treats a DeleteTpmKeyBackupMsg failure as fatal (calls trigger.fail),
but TPM key backup cleanup is best-effort and should not abort the overall
revert; change the CloudBusCallBack in the "delete-tpm-key-backup" Flow (the
bus.send callback handling DeleteTpmKeyBackupMsg) so that on r.isSuccess() it
clears context.tpmKeyBackupUuid and calls trigger.next(), and on failure it logs
a warning (including r.getError()) instead of calling trigger.fail, then still
calls trigger.next() so the main revert continues.
🪄 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: 69c493af-229e-40ed-98ec-fd7f2e015ac9

📥 Commits

Reviewing files that changed from the base of the PR and between 9508f2e and 77c5bb0.

⛔ Files ignored due to path filters (1)
  • conf/persistence.xml is excluded by !**/*.xml
📒 Files selected for processing (10)
  • compute/src/main/java/org/zstack/compute/vm/devices/DummyTpmEncryptedResourceKeyBackend.java
  • compute/src/main/java/org/zstack/compute/vm/devices/TpmEncryptedResourceKeyBackend.java
  • header/src/main/java/org/zstack/header/tpm/entity/TpmKeyBackupVO.java
  • header/src/main/java/org/zstack/header/tpm/entity/TpmKeyBackupVO_.java
  • header/src/main/java/org/zstack/header/tpm/message/DeleteTpmKeyBackupMsg.java
  • header/src/main/java/org/zstack/header/tpm/message/DeleteTpmKeyBackupReply.java
  • header/src/main/java/org/zstack/header/tpm/message/RestoreTpmEncryptionKeyMsg.java
  • header/src/main/java/org/zstack/header/tpm/message/RestoreTpmEncryptionKeyReply.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
  • storage/src/main/java/org/zstack/storage/snapshot/group/VolumeSnapshotGroupBase.java

Comment thread plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java Outdated
Comment on lines +595 to +614
.then(Flow.of("delete-tpm-key-backup")
.runIf(data -> context.tpmKeyBackupUuid != null)
.handle(trigger -> {
DeleteTpmKeyBackupMsg delMsg = new DeleteTpmKeyBackupMsg();
delMsg.setTpmUuid(context.tpmUuid);
delMsg.setTpmKeyBackupUuid(context.tpmKeyBackupUuid);
bus.makeTargetServiceIdByResourceUuid(delMsg, SERVICE_ID, context.tpmUuid);
bus.send(delMsg, new CloudBusCallBack(trigger) {
@Override
public void run(MessageReply r) {
if (r.isSuccess()) {
context.tpmKeyBackupUuid = null;
trigger.next();
} else {
trigger.fail(r.getError());
}
}
});
})
.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 | ⚡ Quick win

备份清理失败不应导致整个 revert 操作失败。

此时主要的 revert 操作(卷恢复、TPM 密钥恢复)已经成功完成。TpmKeyBackupVO 是临时性的辅助记录,其清理失败不应该使整个流程失败。建议改为记录警告日志并继续执行。

🔧 建议的修复方案
             .then(Flow.of("delete-tpm-key-backup")
                 .runIf(data -> context.tpmKeyBackupUuid != null)
                 .handle(trigger -> {
                     DeleteTpmKeyBackupMsg delMsg = new DeleteTpmKeyBackupMsg();
                     delMsg.setTpmUuid(context.tpmUuid);
                     delMsg.setTpmKeyBackupUuid(context.tpmKeyBackupUuid);
                     bus.makeTargetServiceIdByResourceUuid(delMsg, SERVICE_ID, context.tpmUuid);
                     bus.send(delMsg, new CloudBusCallBack(trigger) {
                         `@Override`
                         public void run(MessageReply r) {
-                            if (r.isSuccess()) {
-                                context.tpmKeyBackupUuid = null;
-                                trigger.next();
-                            } else {
-                                trigger.fail(r.getError());
+                            if (!r.isSuccess()) {
+                                logger.warn(String.format(
+                                        "failed to delete TpmKeyBackupVO[uuid:%s] after successful revert, but continuing: %s",
+                                        context.tpmKeyBackupUuid, r.getError().getDetails()));
                             }
+                            context.tpmKeyBackupUuid = null;
+                            trigger.next();
                         }
                     });
                 })
                 .build())
🤖 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/snapshot/group/VolumeSnapshotGroupBase.java`
around lines 595 - 614, The delete-tpm-key-backup flow in
VolumeSnapshotGroupBase currently treats a DeleteTpmKeyBackupMsg failure as
fatal (calls trigger.fail), but TPM key backup cleanup is best-effort and should
not abort the overall revert; change the CloudBusCallBack in the
"delete-tpm-key-backup" Flow (the bus.send callback handling
DeleteTpmKeyBackupMsg) so that on r.isSuccess() it clears
context.tpmKeyBackupUuid and calls trigger.next(), and on failure it logs a
warning (including r.getError()) instead of calling trigger.fail, then still
calls trigger.next() so the main revert continues.

Introduce internal TpmKeyBackupVO (no owner) to hold
the VM TPM encryption key during snapshot-group revert

Add DeleteTpmKeyBackupMsg / DeleteTpmKeyBackupReply
to remove the backup VO and its key ref.

Resolves: ZSV-12208
Related: ZSV-11310

DBImpact

Change-Id: I7a7967637667726a727666676a6162787277616e
@MatheMatrix MatheMatrix force-pushed the sync/wenhao.zhang/zsv-8@@2 branch from 77c5bb0 to 121c535 Compare May 11, 2026 08:10
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
conf/db/zsv/V5.1.0__schema.sql (2)

2-2: 💤 Low value

UNIQUE 约束冗余。

uuid 列已定义为 PRIMARY KEY,主键本身就保证了唯一性,无需额外的 UNIQUE 约束。

♻️ 建议的修改
-    `uuid` char(32) NOT NULL UNIQUE,
+    `uuid` char(32) NOT 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 `@conf/db/zsv/V5.1.0__schema.sql` at line 2, 在表定义中移除多余的 UNIQUE 约束:在包含列定义 `uuid
char(32) NOT NULL UNIQUE` 的 SQL 片段中删除 `UNIQUE`,只保留 `uuid char(32) NOT NULL`,因为
`uuid` 已在表的 `PRIMARY KEY` 上被声明,主键已保证唯一性;请更新相关建表语句以移除重复约束并保持主键声明不变。

4-4: 💤 Low value

createDate 的默认值不符合最佳实践。

createDate 使用硬编码的默认值 '1999-12-31 23:59:59',虽然 Java 代码会显式设置该字段,但建议使用 DEFAULT CURRENT_TIMESTAMP 以保持一致性并作为更安全的回退值。

♻️ 建议的修改
-    `createDate` timestamp NOT NULL DEFAULT '1999-12-31 23:59:59',
+    `createDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
🤖 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 `@conf/db/zsv/V5.1.0__schema.sql` at line 4, 当前 schema 中列 createDate 使用硬编码默认值
'1999-12-31 23:59:59',请将其改为使用数据库时间戳回退值:把 createDate 的列定义从 DEFAULT '1999-12-31
23:59:59' 修改为 DEFAULT CURRENT_TIMESTAMP,以确保在未由 Java 明确设置时使用当前时间作为默认值并保持一致性(查找并修改
V5.1.0 migration 中定义 createDate 的列)。
🤖 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 `@conf/db/zsv/V5.1.0__schema.sql`:
- Line 2: 在表定义中移除多余的 UNIQUE 约束:在包含列定义 `uuid char(32) NOT NULL UNIQUE` 的 SQL
片段中删除 `UNIQUE`,只保留 `uuid char(32) NOT NULL`,因为 `uuid` 已在表的 `PRIMARY KEY`
上被声明,主键已保证唯一性;请更新相关建表语句以移除重复约束并保持主键声明不变。
- Line 4: 当前 schema 中列 createDate 使用硬编码默认值 '1999-12-31
23:59:59',请将其改为使用数据库时间戳回退值:把 createDate 的列定义从 DEFAULT '1999-12-31 23:59:59' 修改为
DEFAULT CURRENT_TIMESTAMP,以确保在未由 Java 明确设置时使用当前时间作为默认值并保持一致性(查找并修改 V5.1.0
migration 中定义 createDate 的列)。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3f4a5c4e-e178-433e-af8a-a43aae2deb8e

📥 Commits

Reviewing files that changed from the base of the PR and between 77c5bb0 and 121c535.

⛔ Files ignored due to path filters (1)
  • conf/persistence.xml is excluded by !**/*.xml
📒 Files selected for processing (11)
  • compute/src/main/java/org/zstack/compute/vm/devices/DummyTpmEncryptedResourceKeyBackend.java
  • compute/src/main/java/org/zstack/compute/vm/devices/TpmEncryptedResourceKeyBackend.java
  • conf/db/zsv/V5.1.0__schema.sql
  • header/src/main/java/org/zstack/header/tpm/entity/TpmKeyBackupVO.java
  • header/src/main/java/org/zstack/header/tpm/entity/TpmKeyBackupVO_.java
  • header/src/main/java/org/zstack/header/tpm/message/DeleteTpmKeyBackupMsg.java
  • header/src/main/java/org/zstack/header/tpm/message/DeleteTpmKeyBackupReply.java
  • header/src/main/java/org/zstack/header/tpm/message/RestoreTpmEncryptionKeyMsg.java
  • header/src/main/java/org/zstack/header/tpm/message/RestoreTpmEncryptionKeyReply.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
  • storage/src/main/java/org/zstack/storage/snapshot/group/VolumeSnapshotGroupBase.java
✅ Files skipped from review due to trivial changes (4)
  • header/src/main/java/org/zstack/header/tpm/message/RestoreTpmEncryptionKeyMsg.java
  • header/src/main/java/org/zstack/header/tpm/entity/TpmKeyBackupVO_.java
  • header/src/main/java/org/zstack/header/tpm/message/DeleteTpmKeyBackupReply.java
  • header/src/main/java/org/zstack/header/tpm/entity/TpmKeyBackupVO.java
🚧 Files skipped from review as they are similar to previous changes (5)
  • compute/src/main/java/org/zstack/compute/vm/devices/TpmEncryptedResourceKeyBackend.java
  • header/src/main/java/org/zstack/header/tpm/message/DeleteTpmKeyBackupMsg.java
  • compute/src/main/java/org/zstack/compute/vm/devices/DummyTpmEncryptedResourceKeyBackend.java
  • header/src/main/java/org/zstack/header/tpm/message/RestoreTpmEncryptionKeyReply.java
  • storage/src/main/java/org/zstack/storage/snapshot/group/VolumeSnapshotGroupBase.java

@MatheMatrix
Copy link
Copy Markdown
Owner

Comment from ye.zou:

Code Review: ZSV-12208 — 【5.1.0】物理机详情页 CPU 信息增加显示 Socket 数量

变更概览

  • zstack MR: !9802 (目标分支: zsv_5.1.0)
  • premium MR: !13817 (目标分支: zsv_5.1.0)
  • Jira: ZSV-12208

核心变更

1. zstack 仓库 (!9802)

  • 新增 API 字段: GetCpuInfoExtensionPoint / GetCpuInfoReply 中增加 socketNum 字段
  • 数据层: KvmHostFactory 实现 GetCpuInfoExtensionPoint 接口时,从 HostVOsocketNum 字段读取 Socket 数量
  • 数据库: HostVO / HostAO 已存在 socketNum 字段,无需 schema 变更

2. premium 仓库 (!13817)

  • 前端展示: 物理机详情页 CPU 信息卡片增加 "Socket 数量" 显示项
  • 国际化: 中英文 locale 已补充对应文案
  • UI 位置: 紧跟在 "CPU 数量" 之后,逻辑合理

评审意见

检查项 状态 说明
功能完整性 前后端字段对齐,数据流完整
兼容性 仅新增字段,不影响现有逻辑
国际化 中英文文案已补充
代码风格 符合项目规范
目标分支 ⚠️ 确认合并到 zsv_5.1.0,非 master,请确认是否符合预期

建议

  • 建议确认 socketNum 在旧版本 Host 数据中的默认值处理(是否为 NULL 或 0)
  • 若目标分支确认是 zsv_5.1.0,可正常合并

结论: 代码逻辑清晰,变更范围合理,Approve(目标分支确认后)

@zstack-robot-1
Copy link
Copy Markdown
Collaborator Author

Comment from ye.zou:

Code Review: ZSV-12208 — 【TPM】恢复内存快照时,恢复 TPM 的步骤没有 rollback

变更概览

  • zstack MR: !9802 (目标分支: zsv_5.1.0)
  • premium MR: !13817 (目标分支: zsv_5.1.0)
  • Jira: ZSV-12208

核心变更

1. zstack 仓库 (!9802)

  • 新增 TpmKeyBackupVO 实体: 用于在恢复快照前暂存 VM 当前 TPM 加密密钥
    • TpmKeyBackupVO.java / TpmKeyBackupVO_.java — 实体及 Metamodel
    • conf/db/zsv/V5.1.0__schema.sql — 建表语句
    • conf/persistence.xml — 注册实体类
  • 扩展 RestoreTpmEncryptionKeyMsg: 增加 backupCurrentKey 标志,支持在恢复前自动备份当前密钥
    • RestoreTpmEncryptionKeyReply 增加 tpmKeyBackupUuid 返回字段
  • 新增 DeleteTpmKeyBackupMsg/Reply: 用于清理暂存的备份密钥
  • KvmTpmManager: 实现 handle(RestoreTpmEncryptionKeyMsg) 的 backup/restore 逻辑,异常时清理已创建的备份
  • VolumeSnapshotGroupBase: 集成 TPM key backup 到快照恢复流程
    • 恢复前自动备份当前 TPM key 到 TpmKeyBackupVO
    • 新增 rollback 逻辑:从 TpmKeyBackupVO 恢复原始 key,然后清理备份
    • 新增 delete-tpm-key-backup flow:成功恢复后清理暂存的备份

2. premium 仓库 (!13817)

  • KeyProviderResourceKeyBackend 实现 cleanTpmKeyBackupEncryptedResourceKey 方法
  • conf/persistence.xml 注册 TpmKeyBackupVO

评审意见

检查项 状态 说明
功能完整性 完整实现了 TPM key 的备份、恢复、rollback 和清理流程
数据一致性 异常时清理已创建的 TpmKeyBackupVO,避免脏数据
回滚逻辑 rollback 中先恢复 key 再删除 backup,顺序正确
清理逻辑 成功后在 delete-tpm-key-backup flow 中清理 backup
兼容性 ⚠️ RestoreTpmEncryptionKeyMsg 默认 backupCurrentKey = true,可能影响其他调用方,需确认
目标分支 ⚠️ 目标分支为 zsv_5.1.0,请确认是否符合预期

建议

  1. 建议确认 RestoreTpmEncryptionKeyMsg.backupCurrentKey 默认值设为 true 是否会影响其他现有调用场景(如非快照恢复的 TPM key 恢复)
  2. VolumeSnapshotGroupBase 中的 TODO 注释 // TODO: It should has rollback 已被实现,建议移除

结论

代码逻辑清晰,rollback 机制完整,数据清理到位。确认上述建议后可 Approve。

@ZStack-Robot ZStack-Robot deleted the sync/wenhao.zhang/zsv-8@@2 branch May 11, 2026 10:44
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