Skip to content

<fix>[crypto]: clean TPM key ref on VM destroy#3679

Open
zstack-robot-1 wants to merge 4 commits intofeature-zsv-5.0.0-vm-support-vtpm-and-secucebootfrom
sync/zstackio/remove-resource-keyref@@2
Open

<fix>[crypto]: clean TPM key ref on VM destroy#3679
zstack-robot-1 wants to merge 4 commits intofeature-zsv-5.0.0-vm-support-vtpm-and-secucebootfrom
sync/zstackio/remove-resource-keyref@@2

Conversation

@zstack-robot-1
Copy link
Copy Markdown
Collaborator

Resolves: ZSV-11721

Change-Id: I68676e706f6a786773627074636f6e6a617a6e4f

sync from gitlab !9540

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 3, 2026

Walkthrough

新增 EncryptedResourceKeyManager.deleteRef() 接口及其 Dummy 空实现;在 VM 删除前钩子中调用以移除 VM 的 vTPM 资源密钥引用;VmTpmManager 新增多种删除引用/删除 TPM 的辅助方法;KVM 扩展在 DEK 创建流程中携带并传播 keyProviderName 与 providerUuid/providerName 的更新逻辑。

Changes

Cohort / File(s) Summary
头部接口 & 数据承载类
header/src/main/java/org/zstack/header/keyprovider/EncryptedResourceKeyManager.java
新增接口方法 void deleteRef(String resourceType, String resourceUuid);在内部类 GetOrCreateResourceKeyContextResourceKeyResult 中新增 keyProviderName 字段及其访问器。
VM TPM 扩展点
compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java
类实现新增 VmJustBeforeDeleteFromDbExtensionPoint 并实现 vmJustBeforeDeleteFromDb(VmInstanceInventory),在 VM 从 DB 删除前调用 vmTpmManager.deleteResourceKeyRefForVmTpmIfPresent(...)
VM TPM 管理器
compute/src/main/java/org/zstack/compute/vm/devices/VmTpmManager.java
注入 EncryptedResourceKeyManager 并新增方法:deleteResourceKeyRefForTpm(String)deleteResourceKeyRefForVmTpmIfPresent(String)deleteTpmAndResourceKeyRef(String)deleteTpmAndResourceKeyRef 在尝试删除引用后仍确保删除 TpmVO(try/finally)。
KVM TPM 扩展与管理
plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmExtensions.java, plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
调整 DEK/密钥创建流程:仅当 providerUuidproviderName 均为空时跳过并失败;在创建过程中设置并传递 keyProviderName,成功后从结果更新 providerUuid/providerName/DEK;移除直接调用后端 detach 的代码,改为通过 VmTpmManager 的删除引用逻辑。
Dummy 实现
compute/src/main/java/org/zstack/compute/vm/devices/DummyEncryptedResourceKeyManager.java
新增 @OverridedeleteRef(String resourceType, String resourceUuid) 空实现(不执行任何操作)。

Sequence Diagram(s)

sequenceDiagram
    participant VM as "VM (deletion trigger)"
    participant VmExt as "VmTpmExtensions"
    participant VmMgr as "VmTpmManager"
    participant KeyMgr as "EncryptedResourceKeyManager"
    participant KMS as "Key Provider / Backend"

    rect rgba(200,220,255,0.5)
    VM->>VmExt: vmJustBeforeDeleteFromDb(vmUuid)
    VmExt->>VmMgr: deleteResourceKeyRefForVmTpmIfPresent(vmUuid)
    VmMgr->>VmMgr: 查询 TpmVO 获取 tpmUuid
    VmMgr->>KeyMgr: deleteRef("tpm", tpmUuid)
    KeyMgr->>KMS: 移除或忽略持久化的引用
    end
Loading
sequenceDiagram
    participant KvmExt as "KvmTpmExtensions (DEK 流)"
    participant KeyCtx as "GetOrCreateResourceKeyContext"
    participant KeyMgr as "EncryptedResourceKeyManager"
    participant Result as "ResourceKeyResult"

    rect rgba(200,255,200,0.5)
    KvmExt->>KeyCtx: 构建 context(设置 providerUuid/providerName/可能的 keyProviderName)
    alt provider 信息至少有一项
      KvmExt->>KeyMgr: getOrCreateResourceKey(KeyCtx)
      KeyMgr-->>Result: 返回 keyProviderUuid, keyProviderName, dek
      KvmExt->>KvmExt: 更新 context.providerUuid / context.providerName / DEK
    else providerUuid 与 providerName 均为空
      KvmExt->>KvmExt: 跳过或失败该步骤
    end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 我把引用轻轻拔,deleteRef 不留痕,
虚机别了清又洁,TPM 链接安然存,
小兔一跳去庆祝,接口契约真周到。

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.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 标题'[crypto]: clean TPM key ref on VM destroy'清晰地总结了主要变更,即在VM销毁时清理TPM密钥引用,与整个变更集的核心目标完全相符。
Description check ✅ Passed PR描述虽然简洁,但通过问题编号ZSV-11721、Change-Id和GitLab同步信息与变更集相关联,表明这是密钥引用清理功能的正式同步。

✏️ 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/zstackio/remove-resource-keyref@@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.

🧹 Nitpick comments (1)
compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java (1)

161-169: 建议:考虑 deleteRef 异常处理

forEach 循环中调用 deleteRef 时,如果某次调用抛出异常,后续的 TPM UUID 将不会被处理,可能留下孤立的引用记录。

建议捕获并记录异常,确保所有引用都尝试清理:

♻️ 建议的修改
     `@Override`
     public void afterDestroyVm(VmInstanceInventory inv) {
         List<String> tpmUuids = pendingDestroyTpmUuids.remove(inv.getUuid());
         if (tpmUuids == null || tpmUuids.isEmpty()) {
             return;
         }

-        tpmUuids.forEach(tpmUuid -> resourceKeyManager.deleteRef(TpmVO.class.getSimpleName(), tpmUuid));
+        for (String tpmUuid : tpmUuids) {
+            try {
+                resourceKeyManager.deleteRef(TpmVO.class.getSimpleName(), tpmUuid);
+            } catch (Exception e) {
+                logger.warn(String.format("failed to delete key ref for tpm[uuid:%s] during VM destroy, ignoring: %s",
+                        tpmUuid, e.getMessage()));
+            }
+        }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java`
around lines 161 - 169, The current afterDestroyVm method reads
pendingDestroyTpmUuids and calls resourceKeyManager.deleteRef for each tpmUuid
using forEach, but if deleteRef throws on one UUID the rest won't be processed;
modify afterDestroyVm to iterate over tpmUuids (from
pendingDestroyTpmUuids.remove(inv.getUuid())) with a try/catch around each
resourceKeyManager.deleteRef(TpmVO.class.getSimpleName(), tpmUuid) call, log any
exceptions (including the tpmUuid and inv.getUuid() for context) and continue so
all UUIDs are attempted to be deleted; ensure null/empty checks remain and use
the same identifiers: afterDestroyVm, pendingDestroyTpmUuids,
resourceKeyManager.deleteRef, and TpmVO.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java`:
- Around line 161-169: The current afterDestroyVm method reads
pendingDestroyTpmUuids and calls resourceKeyManager.deleteRef for each tpmUuid
using forEach, but if deleteRef throws on one UUID the rest won't be processed;
modify afterDestroyVm to iterate over tpmUuids (from
pendingDestroyTpmUuids.remove(inv.getUuid())) with a try/catch around each
resourceKeyManager.deleteRef(TpmVO.class.getSimpleName(), tpmUuid) call, log any
exceptions (including the tpmUuid and inv.getUuid() for context) and continue so
all UUIDs are attempted to be deleted; ensure null/empty checks remain and use
the same identifiers: afterDestroyVm, pendingDestroyTpmUuids,
resourceKeyManager.deleteRef, and TpmVO.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f202b3d3-b56d-49b8-b67a-8ca62b1e4053

📥 Commits

Reviewing files that changed from the base of the PR and between b5be037 and 5c27d70.

⛔ Files ignored due to path filters (1)
  • conf/springConfigXml/VmInstanceManager.xml is excluded by !**/*.xml
📒 Files selected for processing (5)
  • compute/src/main/java/org/zstack/compute/vm/devices/DummyEncryptedResourceKeyManager.java
  • compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java
  • header/src/main/java/org/zstack/header/keyprovider/EncryptedResourceKeyManager.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmExtensions.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java

Delay/trash deletion no longer drops EncryptedResourceKeyRef;
cleanup runs in vmJustBeforeDeleteFromDb (expunge/direct delete).
Centralize ref delete in VmTpmManager; wire RemoveTpm/add-tpm
rollback and drop unused destroy extension from VmTpmExtensions.

Resolves: ZSV-11721

Change-Id: I68676e706f6a786773627074636f6e6a617a6e4f
@MatheMatrix MatheMatrix force-pushed the sync/zstackio/remove-resource-keyref@@2 branch from 5c27d70 to 70f437f Compare April 3, 2026 16:14
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@compute/src/main/java/org/zstack/compute/vm/devices/VmTpmManager.java`:
- Around line 73-75: The current deleteTpmAndResourceKeyRef method calls
deleteResourceKeyRefForTpm(tpmUuid) then deleteTpmVO(tpmUuid) sequentially, but
if deleteResourceKeyRefForTpm throws the TPM record (TpmVO) may not be removed;
change deleteTpmAndResourceKeyRef to call deleteResourceKeyRefForTpm inside a
try block and always call deleteTpmVO in a finally block so the TPM row is
deleted regardless of exceptions; keep the same method names
(deleteTpmAndResourceKeyRef, deleteResourceKeyRefForTpm, deleteTpmVO) and
preserve existing exception propagation/logging behavior.
🪄 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: 50c7ae3a-87d8-4ddd-a783-5bc716608c19

📥 Commits

Reviewing files that changed from the base of the PR and between 5c27d70 and 70f437f.

⛔ Files ignored due to path filters (1)
  • conf/springConfigXml/VmInstanceManager.xml is excluded by !**/*.xml
📒 Files selected for processing (6)
  • compute/src/main/java/org/zstack/compute/vm/devices/DummyEncryptedResourceKeyManager.java
  • compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java
  • compute/src/main/java/org/zstack/compute/vm/devices/VmTpmManager.java
  • header/src/main/java/org/zstack/header/keyprovider/EncryptedResourceKeyManager.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmExtensions.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
🚧 Files skipped from review as they are similar to previous changes (4)
  • compute/src/main/java/org/zstack/compute/vm/devices/DummyEncryptedResourceKeyManager.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmExtensions.java
  • header/src/main/java/org/zstack/header/keyprovider/EncryptedResourceKeyManager.java

@ZStack-Robot
Copy link
Copy Markdown
Collaborator

Comment from yaohua.wu:

Review: MR !9540 — ZSV-11721 (zstack repo)

联合审查:本 review 覆盖 zstackio/zstack !9540 与 zstackio/premium !13421 两个 MR,因为它们是同一变更的 interface/impl 两侧。

总体评价

目标明确:将 TPM key ref 的清理从分散的 detachKeyProviderFromTpm 调用集中到 VmTpmManager + EncryptedResourceKeyManager.deleteRef(),并通过 VmJustBeforeDeleteFromDbExtensionPoint 补全 VM expunge/直删时的 ref 清理路径。同时引入 provider name fallback 机制和 ||&& 逻辑修正。整体设计方向正确。


🔴 Critical

1. [MR 合并状态] MR 存在合并冲突

merge_status: "cannot_be_merged",有 6 个 diverged commits。需要 rebase 到最新 feature-zsv-5.0.0-vm-support-vtpm-and-secuceboot 后重新验证。


🟡 Warning

1. [VmTpmManager.java:73-75] deleteTpmAndResourceKeyRef 丢失 try-finally 保护

旧代码 afterRollbackPersistVmInstanceVO 中使用 try-finally 确保即使 key ref 删除失败,TpmVO 仍会被清理:

// 旧代码(有 try-finally 保护)
try {
    resourceKeyBackend.detachKeyProviderFromTpm(tpmUuid);
} finally {
    vmTpmManager.deleteTpmVO(tpmUuid);
}

新代码顺序调用,无保护:

public void deleteTpmAndResourceKeyRef(String tpmUuid) {
    deleteResourceKeyRefForTpm(tpmUuid);  // 若此处抛异常...
    deleteTpmVO(tpmUuid);                 // ...此行不会执行,TpmVO 泄漏
}

影响范围:两处调用受影响:

  • VmTpmExtensions.afterRollbackPersistVmInstanceVO — VM 创建回滚时
  • KvmTpmManager addTpm 的 rollback lambda — 添加 TPM 回滚时

建议恢复 try-finally 语义:

public void deleteTpmAndResourceKeyRef(String tpmUuid) {
    try {
        deleteResourceKeyRefForTpm(tpmUuid);
    } finally {
        deleteTpmVO(tpmUuid);
    }
}

CodeRabbit 也标记了此问题,建议采纳。

2. [KvmTpmExtensions.java:173,182] ||&& 逻辑变更需确认语义正确性

// 旧:有任一为空就 skip/fail
(StringUtils.isBlank(context.providerUuid) || StringUtils.isBlank(context.providerName))
// 新:两者都为空才 skip/fail
(StringUtils.isBlank(context.providerUuid) && StringUtils.isBlank(context.providerName))

变更后语义:只要有 UUID 或 name 中的任意一个,就会进入 getOrCreateKey 流程。这依赖 premium 侧的 resolveProvider() 能仅凭 name 解析出唯一 provider。

语义本身是合理的(配合 name fallback),但需注意:如果 providerUuid 非空但指向已删除的 provider,而 providerName 也设了值,resolveProvider 会先按 UUID 查不到,再按 name fallback。这是预期行为还是应该报错?建议在 resolveProvider 的 warn 日志中增加对此场景的明确说明。

3. [VmTpmExtensions.java:127-141] vmJustBeforeDeleteFromDb 路径与 removeTpmFromVm 的重复清理

当用户先调用 RemoveTpm(删除 TPM 设备),然后 expunge VM 时:

  • RemoveTpm 流程中 deleteResourceKeyRefForTpm 已删除 ref
  • 之后 VM expunge 触发 vmJustBeforeDeleteFromDbdeleteResourceKeyRefForVmTpmIfPresent 再次尝试查 TpmVO

此时 TpmVO 已在 RemoveTpm 流程中被删除,所以 findValue() 返回 null,不会执行 deleteRef。这是安全的(幂等),但建议在 Javadoc 中说明此 defensive 设计。


🟢 Suggestion

1. [VmTpmManager.java:49-51] deleteResourceKeyRefForTpm 缺少日志

关键资源清理操作缺少日志输出,不利于问题排查:

public void deleteResourceKeyRefForTpm(String tpmUuid) {
    logger.debug(String.format("deleting encrypted resource key ref for TpmVO[uuid:%s]", tpmUuid));
    resourceKeyManager.deleteRef(TpmVO.class.getSimpleName(), tpmUuid);
}

2. [KvmTpmExtensions.java:199] context.providerUuid 更新时机

context.providerUuid = result.getKeyProviderUuid();

getOrCreateKey 成功回调中更新 context.providerUuid 是正确的做法,确保后续 flow step 使用解析后的 UUID。但 context.providerUuid 是 package-private 字段直接赋值,如果未来有其他 flow 步骤在并发中读取该字段,可能存在可见性问题。当前流程是串行的所以没问题,仅作为未来注意点。

Verdict: REVISION_REQUIRED

主要原因:合并冲突需解决;deleteTpmAndResourceKeyRef 建议恢复 try-finally。


🤖 Robot Reviewer

zhong.zhou added 2 commits April 4, 2026 16:21
Delay/trash deletion no longer drops EncryptedResourceKeyRef;
cleanup runs in vmJustBeforeDeleteFromDb (expunge/direct delete).
Centralize ref delete in VmTpmManager; wire RemoveTpm/add-tpm
rollback and drop unused destroy extension from VmTpmExtensions.

Resolves: ZSV-11721

Change-Id: I68676e706f6a786773627074636f6e6a617a6e4f
…m-and-secuceboot' into remove-resource-keyref@@2
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)
compute/src/main/java/org/zstack/compute/vm/devices/VmTpmManager.java (1)

52-54: 建议添加 debug 日志记录 ref 删除尝试。

根据 PR 评审建议,在 deleteResourceKeyRefForTpm 中添加 debug 日志有助于追踪 ref 删除操作,便于问题排查。

♻️ 建议的修改
 public void deleteResourceKeyRefForTpm(String tpmUuid) {
+    logger.debug(String.format("Deleting resource key ref for TPM[uuid:%s]", tpmUuid));
     resourceKeyManager.deleteRef(TpmVO.class.getSimpleName(), tpmUuid);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@compute/src/main/java/org/zstack/compute/vm/devices/VmTpmManager.java` around
lines 52 - 54, 在 VmTpmManager.deleteResourceKeyRefForTpm 中,在调用
resourceKeyManager.deleteRef(TpmVO.class.getSimpleName(), tpmUuid) 之前添加一条 debug
日志,记录尝试删除的资源类型和 tpmUuid(例如 logger.debug("Deleting resource key ref for {}
id={}", TpmVO.class.getSimpleName(), tpmUuid)),以便追踪删除操作;如果 deleteRef
返回或抛出异常,可以在调用后补充相应的 debug/trace 日志或在 catch 块中记录错误细节以便排查。
compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java (1)

72-77: SQLBatch 包装器可简化。

deleteTpmAndResourceKeyRef 是单个方法调用,且内部已包含 try-finally 逻辑。外层的 SQLBatch 包装可能是为了与原有代码风格保持一致,但从功能上看并非必需。如果 deleteTpmAndResourceKeyRef 内部的数据库操作需要在同一事务中执行,可以考虑在该方法内部处理。

♻️ 可选简化
         if (tpmUuid == null) {
             return;
         }
 
-        new SQLBatch() {
-            `@Override`
-            protected void scripts() {
-                vmTpmManager.deleteTpmAndResourceKeyRef(tpmUuid);
-            }
-        }.execute();
+        vmTpmManager.deleteTpmAndResourceKeyRef(tpmUuid);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java`
around lines 72 - 77, The SQLBatch wrapper around the single call to
vmTpmManager.deleteTpmAndResourceKeyRef(tpmUuid) is unnecessary; remove the new
SQLBatch() { ... }.execute() block in VmTpmExtensions and invoke
vmTpmManager.deleteTpmAndResourceKeyRef(tpmUuid) directly (or, if transactional
semantics are required, ensure deleteTpmAndResourceKeyRef handles its own
transaction/try-finally inside vmTpmManager). This simplifies the code by
eliminating the redundant SQLBatch wrapper while preserving existing
error/transaction handling in deleteTpmAndResourceKeyRef.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java`:
- Around line 72-77: The SQLBatch wrapper around the single call to
vmTpmManager.deleteTpmAndResourceKeyRef(tpmUuid) is unnecessary; remove the new
SQLBatch() { ... }.execute() block in VmTpmExtensions and invoke
vmTpmManager.deleteTpmAndResourceKeyRef(tpmUuid) directly (or, if transactional
semantics are required, ensure deleteTpmAndResourceKeyRef handles its own
transaction/try-finally inside vmTpmManager). This simplifies the code by
eliminating the redundant SQLBatch wrapper while preserving existing
error/transaction handling in deleteTpmAndResourceKeyRef.

In `@compute/src/main/java/org/zstack/compute/vm/devices/VmTpmManager.java`:
- Around line 52-54: 在 VmTpmManager.deleteResourceKeyRefForTpm 中,在调用
resourceKeyManager.deleteRef(TpmVO.class.getSimpleName(), tpmUuid) 之前添加一条 debug
日志,记录尝试删除的资源类型和 tpmUuid(例如 logger.debug("Deleting resource key ref for {}
id={}", TpmVO.class.getSimpleName(), tpmUuid)),以便追踪删除操作;如果 deleteRef
返回或抛出异常,可以在调用后补充相应的 debug/trace 日志或在 catch 块中记录错误细节以便排查。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 572a4d89-341a-4e0e-bac4-d4e48dccaa89

📥 Commits

Reviewing files that changed from the base of the PR and between 70f437f and 771fefb.

⛔ Files ignored due to path filters (1)
  • conf/springConfigXml/VmInstanceManager.xml is excluded by !**/*.xml
📒 Files selected for processing (3)
  • compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java
  • compute/src/main/java/org/zstack/compute/vm/devices/VmTpmManager.java
  • plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java

…onflict

Integrate origin/remove-resource-keyref@@2 after divergent pushes; conflict in
VmTpmManager/VmTpmExtensions resolved keeping try/finally deleteTpmAndResourceKeyRef
and extended javadoc.

Resolves: ZSV-11721

Change-Id: I00d3201a733026a6c82edc281dcb6fa760e6ddfd
@MatheMatrix MatheMatrix force-pushed the sync/zstackio/remove-resource-keyref@@2 branch from 771fefb to 0ed8cb6 Compare April 4, 2026 11:02
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