Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,23 @@ public void run(MessageReply reply) {
spec.getVmInventory().getUuid(), spec.getVmInventory().getName(),
spec.getDestHost().getUuid(), spec.getDestHost().getName(), reply.getError()));

if (reply.getError().isError(HostErrors.OPERATION_FAILURE_GC_ELIGIBLE)) {
String gcName = String.format("gc-vm-%s-on-host-%s", spec.getVmInventory().getUuid(), spec.getDestHost().getUuid());

DeleteVmGC gc = new DeleteVmGC();
gc.NAME = gcName;
gc.hostUuid = spec.getVmInventory().getHostUuid();
gc.inventory = spec.getVmInventory();
if (gc.existedAndNotCompleted()) {
logger.debug(String.format("There is already a DeleteVmGC of vm[uuid:%s] " +
"on host[uuid:%s], skip.", spec.getVmInventory().getUuid(), spec.getDestHost().getUuid()));
} else {
gc.submit();
}
// Always submit GC to clean up the VM on the hypervisor,
// regardless of whether the error is GC_ELIGIBLE or not.
// This prevents orphaned VMs and GPU dirty data (ZSTAC-68874).
String gcName = String.format("gc-vm-%s-on-host-%s", spec.getVmInventory().getUuid(), spec.getDestHost().getUuid());

DeleteVmGC gc = new DeleteVmGC();
gc.NAME = gcName;
gc.hostUuid = spec.getVmInventory().getHostUuid();
gc.inventory = spec.getVmInventory();
if (gc.existedAndNotCompleted()) {
logger.debug(String.format("There is already a DeleteVmGC of vm[uuid:%s] " +
"on host[uuid:%s], skip.", spec.getVmInventory().getUuid(), spec.getDestHost().getUuid()));
} else {
gc.submit();
}
Comment on lines +85 to +96
Copy link

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
# 查找 DeleteVmGC 类的实现
ast-grep --pattern $'class DeleteVmGC {
  $$$
}'

# 查找 existedAndNotCompleted 方法的实现
rg -n -A 10 'existedAndNotCompleted' --type java

Repository: MatheMatrix/zstack

Length of output: 6777


🏁 Script executed:

#!/bin/bash
# 查找 DeleteVmGC 类的定义和实现
find . -type f -name "*.java" | xargs grep -l "class DeleteVmGC"

# 查看 DeleteVmGC 的完整实现
rg -B 5 -A 30 "class DeleteVmGC" --type java

Repository: MatheMatrix/zstack

Length of output: 3642


🏁 Script executed:

#!/bin/bash
# 查看 VmCreateOnHypervisorFlow 完整代码段
rg -B 20 -A 10 "setHostUuid" compute/src/main/java/org/zstack/compute/vm/VmCreateOnHypervisorFlow.java

Repository: MatheMatrix/zstack

Length of output: 3295


gc.hostUuid 应使用 spec.getDestHost().getUuid() 而非 spec.getVmInventory().getHostUuid(),确保 GC 任务在正确的主机上执行。

在 VM 创建失败的回滚流程中,VM 被创建在 destHost 上。DeleteVmGChostUuid 字段被用于:

  1. 匹配主机事件(HOST_DELETED_PATHHOST_STATUS_CHANGED_PATH
  2. 查询主机状态以决定是否执行清理

第 85 行的 gcName 和第 93 行的日志都正确地使用了 spec.getDestHost().getUuid(),但第 89 行的 gc.hostUuid 使用了 spec.getVmInventory().getHostUuid(),导致 GC 可能在错误的主机上执行清理或无法正确监听主机事件。

建议修复
                     DeleteVmGC gc = new DeleteVmGC();
                     gc.NAME = gcName;
-                    gc.hostUuid = spec.getVmInventory().getHostUuid();
+                    gc.hostUuid = spec.getDestHost().getUuid();
                     gc.inventory = spec.getVmInventory();
🤖 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/VmCreateOnHypervisorFlow.java`
around lines 85 - 96, In VmCreateOnHypervisorFlow, the DeleteVmGC is being
registered with the wrong host UUID: change gc.hostUuid from
spec.getVmInventory().getHostUuid() to spec.getDestHost().getUuid() so the GC
(DeleteVmGC) runs and listens for host events on the actual destination host
where the VM was created; update the assignment near gcName creation (refer to
DeleteVmGC, gc.hostUuid, gcName and the logger.debug call) to use
spec.getDestHost().getUuid().


if (!reply.getError().isError(HostErrors.OPERATION_FAILURE_GC_ELIGIBLE)) {
VmTracerCanonicalEvents.OperateFailOnHypervisorData data = new VmTracerCanonicalEvents.OperateFailOnHypervisorData();
data.setHostUuid(spec.getVmInventory().getHostUuid());
data.setVmUuid(spec.getVmInventory().getUuid());
Expand Down