<fix>[vm]: add MetadataImpact#3583
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Walkthrough新增完整的虚拟机实例元数据子系统:消息/API/SDK/扩展点/数据库表/后端实现及 GC/校验,支持元数据的写入、读取、扫描、替换、清理与注册,并在多种主存储插件(Local/NFS)与 KVM 代理中实现端到端交互。 Changes
Sequence Diagram(s)sequenceDiagram
participant Client as API客户端
participant API as API层
participant PS as 主存储服务
participant Plugin as PathBuilder/后端插件
participant Host as 宿主机代理
Client->>API: 发起 注册/更新/清理/扫描 请求
API->>PS: 发送 Update/Get/Scan/Cleanup Msg
PS->>Plugin: 请求 buildVmMetadataPath/buildMetadataDir(若需)
Plugin-->>PS: 返回 metadataPath / metadataDir
PS->>Host: 通过后端发起 HTTP Cmd(Write/Get/Scan/Cleanup)
Host-->>PS: Cmd Rsp(metadata 或 entries)
PS-->>API: 返回 Reply/Event 给 Client
sequenceDiagram
participant Flow as Expunge/Flow
participant GC as GC 触发器
participant PS as 主存储服务
participant Bus as CloudBus
participant Host as 宿主机代理
Flow->>PS: 创建 CleanupVmInstanceMetadataOnPrimaryStorageMsg 并发送
PS->>Bus: 定位 primaryStorage 服务并转发消息
Bus->>PS: 收到回复
PS->>GC: 在失败时提交/调度 GC(或 GC 自行触发前置检查)
GC->>PS: 触发 CleanupMsg 或 取消(若 PS 不存在)
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (15)
header/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.java (1)
6-10: 扩展点接口方法建议补充 Javadoc。当前接口方法缺少注释,后续实现方难以统一理解参数语义(尤其
resourceType、now)。建议在接口层补齐简明 Javadoc。可选修改示例
public interface VmMetadataResourcePersistExtensionPoint { + /** + * `@return` 当前扩展支持的主存储类型 + */ String getPrimaryStorageType(); + + /** + * 卷元数据持久化后的回调。 + */ void afterVolumePersist(String primaryStorageUuid, String resourceUuid, String resourceType, String hostUuid, long size, Timestamp now); + + /** + * 快照元数据持久化后的回调。 + */ void afterSnapshotPersist(String primaryStorageUuid, String resourceUuid, String resourceType, String hostUuid, long size, Timestamp now); }As per coding guidelines: “接口方法不应有多余的修饰符(例如 public),且必须配有有效的 Javadoc 注释。”
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@header/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.java` around lines 6 - 10, 为接口 VmMetadataResourcePersistExtensionPoint 的方法补充简明 Javadoc:在 getPrimaryStorageType(), afterVolumePersist(String primaryStorageUuid, String resourceUuid, String resourceType, String hostUuid, long size, Timestamp now) 和 afterSnapshotPersist(...) 上分别加入方法注释,明确说明返回值语义(getPrimaryStorageType 返回的存储类型标识),以及每个参数含义,尤其注明 resourceType 的取值范围/语义(例如是 Volume/Snapshot/其它资源类型)和 now 表示的时间语义(例如为持久化时间或事件时间,时区/精度要求);同时确保接口方法不使用多余修饰符(保持默认可见性)。compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java (1)
140-140: 为VM_METADATA_LAST_REFRESH_VERSION补充校验与默认值。Line 140 的新配置项缺少显式约束,建议至少限制为非负数字并提供默认值,避免非法配置值进入运行期路径。
可选修改示例
+ `@GlobalConfigValidation`(numberGreaterThan = -1) + `@GlobalConfigDef`(defaultValue = "0", type = Long.class, description = "vm metadata last refresh version") public static GlobalConfig VM_METADATA_LAST_REFRESH_VERSION = new GlobalConfig(CATEGORY, "vm.metadata.lastRefreshVersion");🤖 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/VmGlobalConfig.java` at line 140, 为 VM_METADATA_LAST_REFRESH_VERSION 添加显式默认值与校验:在 VmGlobalConfig 中对静态常量 VM_METADATA_LAST_REFRESH_VERSION 设置一个合理默认(例如 "0")并在 GlobalConfig 或配置注册处添加校验回调/规则,确保值为非负整数(>=0),在解析/设置时拒绝或纠正非法值并记录错误。定位符:VM_METADATA_LAST_REFRESH_VERSION、VmGlobalConfig、GlobalConfig,修改时把默认值注入并为该项注册非负数字校验逻辑(或抛出/回退到默认)。header/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.java (1)
3-14: 建议添加toString()方法此数据类用于 API 响应和日志记录场景,添加
toString()方法可以方便调试和日志输出。此外,如果此类会用于集合比较,也建议实现equals()和hashCode()方法。♻️ 建议添加的方法
+ `@Override` + public String toString() { + return String.format("VmMetadataScanEntry{vmUuid='%s', vmName='%s', metadataPath='%s', incomplete=%s}", + vmUuid, vmName, metadataPath, incomplete); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@header/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.java` around lines 3 - 14, Add a clear toString() implementation to the VmMetadataScanEntry class that returns a readable representation of all fields (vmUuid, vmName, vmCategory, architecture, schemaVersion, metadataPath, hostUuid, sizeBytes, lastUpdateTime, incomplete) for logging and API/debug output; additionally implement equals(Object) and hashCode() based on the same identifying fields (at minimum vmUuid and metadataPath or choose all fields consistently) so instances can be compared and used in collections reliably, and ensure both methods are placed in VmMetadataScanEntry alongside existing getters/setters.plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java (2)
29-45: 重复的数据库查询
buildMetadataDir和buildVmMetadataPath方法都执行相同的数据库查询来获取mountPath。如果这两个方法经常被连续调用,可以考虑提取一个共享的私有方法来减少代码重复。♻️ 建议的重构
+ private String getMountPath(String primaryStorageUuid) { + String mountPath = Q.New(PrimaryStorageVO.class) + .select(PrimaryStorageVO_.mountPath) + .eq(PrimaryStorageVO_.uuid, primaryStorageUuid) + .findValue(); + if (mountPath == null) { + throw new CloudRuntimeException(String.format( + "cannot find mountPath for NFS primary storage[uuid:%s]", primaryStorageUuid)); + } + return mountPath; + } + `@Override` public String buildMetadataDir(String primaryStorageUuid) { - String mountPath = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.mountPath).eq(PrimaryStorageVO_.uuid, primaryStorageUuid).findValue(); - if (mountPath == null) { - throw new CloudRuntimeException(String.format("cannot find mountPath for NFS primary storage[uuid:%s]", primaryStorageUuid)); - } + String mountPath = getMountPath(primaryStorageUuid); return String.format("%s/%s", mountPath, VmInstanceMetadataConstants.METADATA_DIR_NAME); } `@Override` public String buildVmMetadataPath(String primaryStorageUuid, String vmInstanceUuid) { - String mountPath = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.mountPath).eq(PrimaryStorageVO_.uuid, primaryStorageUuid).findValue(); - if (mountPath == null) { - throw new CloudRuntimeException(String.format("cannot find mountPath for NFS primary storage[uuid:%s]", primaryStorageUuid)); - } + String mountPath = getMountPath(primaryStorageUuid); return String.format("%s/%s/%s%s", mountPath, VmInstanceMetadataConstants.METADATA_DIR_NAME, vmInstanceUuid, VmInstanceMetadataConstants.FILE_METADATA_SUFFIX); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java` around lines 29 - 45, buildMetadataDir and buildVmMetadataPath duplicate the same DB query to get mountPath; extract a private helper like getMountPath(String primaryStorageUuid) that performs Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.mountPath).eq(PrimaryStorageVO_.uuid, primaryStorageUuid).findValue(), throws the same CloudRuntimeException when null, and then call this helper from both buildMetadataDir and buildVmMetadataPath to remove the duplicated query logic.
87-99: 硬编码的路径标记可以提取为常量
extractOldPrefix方法中的markers数组是硬编码的魔术字符串。建议将其提取为类级别的常量,以提高可维护性和可读性。♻️ 建议的重构
+ private static final String[] PATH_MARKERS = { + "/rootVolumes/", "/dataVolumes/", "/volumeSnapshots/", "/memory/" + }; + private String extractOldPrefix(String path) { if (path == null || !path.startsWith("/")) { return null; } - String[] markers = {"/rootVolumes/", "/dataVolumes/", "/volumeSnapshots/", "/memory/"}; - for (String marker : markers) { + for (String marker : PATH_MARKERS) { int idx = path.indexOf(marker); if (idx >= 0) { return path.substring(0, idx + 1); } } return null; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java` around lines 87 - 99, Extract the hard-coded path markers in extractOldPrefix into class-level constants to avoid magic strings: introduce a private static final String[] OLD_PATH_MARKERS (or individual constants like OLD_ROOT_VOLUMES = "/rootVolumes/" etc.) in NfsVmMetadataExtension and replace the local markers array in extractOldPrefix to reference these constants; ensure the behavior and ordering remain the same and update any javadoc/comments to reflect the new constants.header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.java (1)
10-17: REST API 路径设计建议当前 API 路径为
/primary-storage/vm-instances/metadata,uuid作为查询参数传递。按照 RESTful 设计原则,建议将uuid作为路径参数,使用类似/vm-instances/{uuid}/primary-storage-metadata或/primary-storage/{primaryStorageUuid}/vm-instances/{uuid}/metadata的形式,这样更能清晰表达资源层级关系。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.java` around lines 10 - 17, The REST path should express the resource hierarchy by moving the vm instance uuid into the URL instead of a query parameter: update the `@RestRequest` path on class APIGetVmInstanceMetadataFromPrimaryStorageMsg to use a path parameter (e.g. "/vm-instances/{uuid}/primary-storage-metadata" or "/primary-storage/{primaryStorageUuid}/vm-instances/{uuid}/metadata") and ensure the private String uuid field is declared/annotated to bind from the path (keep `@APIParam`(resourceType = VmInstanceVO.class) and mark it required if applicable) so the framework maps the path variable to the uuid field; adjust any consumers that construct the URL to pass uuid in the path.header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.java (1)
22-25:__example__()方法可以增强当前返回空的回复对象。建议添加示例数据以生成更有意义的 API 文档。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.java` around lines 22 - 25, APIScanVmInstanceMetadataFromPrimaryStorageReply.__example__() 目前返回空对象,需填充示例数据以改善文档;在该方法内构造一个或多个示例 VmInstanceMetadataInventory(可调用 VmInstanceMetadataInventory.__example__() 或手动设置关键字段),通过 reply.setInventories(...) 将示例列表放入回复,并设置 reply.setTotal(...) 或其他相关元数据字段以反映示例数量,确保返回的示例包含典型字段(如 vmUuid、hostUuid、path 等)以便生成更有意义的 API 文档。header/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.java (1)
17-18: 建议:uuid字段缺少@APIParam注解。与其他 VM API 消息类(如
APISetVmSshKeyMsg)相比,此处的uuid字段缺少@APIParam(resourceType = VmInstanceVO.class)注解。这是一个已存在的问题,不是本 PR 引入的,但建议后续补充以保持一致性并启用框架的资源验证功能。♻️ 建议的修复
+import org.zstack.header.message.APIParam; + public class APIDeleteVmSshKeyMsg extends APIMessage implements VmInstanceMessage { + `@APIParam`(resourceType = VmInstanceVO.class) private String uuid;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@header/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.java` around lines 17 - 18, The uuid field in APIDeleteVmSshKeyMsg lacks the `@APIParam` annotation used elsewhere; update the APIDeleteVmSshKeyMsg class by annotating the private String uuid field with `@APIParam`(resourceType = VmInstanceVO.class) (and add any missing imports for APIParam and VmInstanceVO) so the framework can perform resource validation consistent with APISetVmSshKeyMsg.header/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.java (1)
23-24: 命名规范问题:成员变量SshKey应使用 lowerCamelCase。根据编码规范,成员变量应使用 lowerCamelCase 风格。
SshKey应改为sshKey。这是一个已存在的问题,不是本 PR 引入的,可考虑在后续修复。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@header/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.java` around lines 23 - 24, Rename the member field SshKey to lowerCamelCase sshKey in class APISetVmSshKeyMsg; update all usages and references to this field (including any getters/setters, constructors, builders, JSON/serialization annotations, and unit tests) so they refer to sshKey consistently, and ensure the public accessor methods remain correct (getSshKey/setSshKey or adjust if you rename them) to preserve API compatibility; run tests to verify no breakage.sdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.java (1)
3-3: 冗余的导入声明
VmInstanceInventory与RegisterVmInstanceFromMetadataResult位于同一个包org.zstack.sdk中,无需显式导入。♻️ 建议移除冗余导入
package org.zstack.sdk; -import org.zstack.sdk.VmInstanceInventory; - public class RegisterVmInstanceFromMetadataResult {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.java` at line 3, 在 RegisterVmInstanceFromMetadataResult 类中移除对同一包 org.zstack.sdk 下的 VmInstanceInventory 的冗余导入声明(去掉 import org.zstack.sdk.VmInstanceInventory;),因为 VmInstanceInventory 与 RegisterVmInstanceFromMetadataResult 位于同一包中无需显式导入;确认类中不再存在对该导入行的依赖(若有,保留直接引用类型名即可)。header/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.java (1)
19-21: 建议统一resolveVmUuids的非空契约描述。当前注释写“never null”,但批量方法仍显式容忍
null返回。建议二选一:要么把注释改为“可为空并会被忽略”,要么强制实现返回空列表,避免契约歧义。Also applies to: 36-39
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@header/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.java` around lines 19 - 21, Unify the non-null contract for list-returning resolvers in VmUuidFromApiResolver: either update the JavaDoc of resolveVmUuids (and any other list-returning methods in the interface) to state that null is allowed and will be ignored, or enforce a non-null contract by changing implementations and the JavaDoc to require returning an empty list instead of null; locate resolveVmUuids and other list-returning methods in the VmUuidFromApiResolver interface, update their Javadoc to match the chosen contract, and if you choose the non-null option, update all implementations to return Collections.emptyList() (or equivalent) instead of null.header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.java (1)
28-28: 考虑后续优化:避免布尔参数,采用更具描述性的 API虽然参数名称
storageStructureChange和 Javadoc 注释已提供清晰的语义说明,但遵循编码准则"避免使用布尔型参数造成含义不明确",可在后续有实际调用点时考虑重构为具名方法(如markDirtyForStorageStructureChange(...))或使用枚举。当前接口定义已充分自解释,此优化可作为可选项。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.java` at line 28, The method signature markDirty(String vmInstanceUuid, boolean storageStructureChange) uses a boolean flag that hurts readability; refactor by replacing the boolean with a more descriptive API—either add separate methods such as markDirtyForStorageStructureChange(String vmInstanceUuid) and markDirtyForRuntimeChange(String vmInstanceUuid) or introduce an enum (e.g., DirtyReason { STORAGE_STRUCTURE_CHANGE, RUNTIME_CHANGE }) and change the signature to markDirty(String vmInstanceUuid, DirtyReason reason); update implementations of VmMetadataDirtyService and all callers to use the new method(s) and remove the boolean overload.compute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.java (1)
63-68: 建议增加psType的 null 检查。当主存储在流程执行期间被删除时,
psType查询可能返回 null,传递给getExtensionFromMap可能导致意外行为。♻️ 建议的修改
String psType = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.type).eq(PrimaryStorageVO_.uuid, psUuid).findValue(); + if (psType == null) { + logger.debug(String.format("[MetadataExpunge] vm[uuid:%s] primary storage[uuid:%s] no longer exists, " + + "skipping metadata cleanup", vmUuid, psUuid)); + trigger.next(); + return; + } VmMetadataPathBuildExtensionPoint ext = pluginRgty.getExtensionFromMap(psType, VmMetadataPathBuildExtensionPoint.class);🤖 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/VmExpungeMetadataFlow.java` around lines 63 - 68, The code obtains psType via Q.New(PrimaryStorageVO.class)...findValue() and immediately passes it to pluginRgty.getExtensionFromMap; add a null check for psType after the query (before calling pluginRgty.getExtensionFromMap) and if psType is null, call trigger.next() and return (optionally log a debug/warn mentioning missing PrimaryStorageVO), so getExtensionFromMap is only invoked with a non-null psType; reference symbols: psType, Q.New(PrimaryStorageVO.class)...findValue(), pluginRgty.getExtensionFromMap(..., VmMetadataPathBuildExtensionPoint.class), and trigger.next().header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.java (1)
10-12: 考虑使用原始类型int替代Integer。
totalCleaned和totalFailed字段使用包装类型Integer,在使用时可能需要进行 null 检查。根据 ZStack 代码库的惯例,对于数值字段优先使用原始类型(如int)以避免 NPE 风险和不必要的装箱/拆箱操作。♻️ 建议的修改
- private Integer totalCleaned; - private Integer totalFailed; + private int totalCleaned; + private int totalFailed;Based on learnings: "在 ZStack 代码库中,当响应类包含数值字段(如 size、actualSize)时,优先使用原始类型(long)而不是包装类型(Long),以避免 NPE 风险和不必要的装箱/拆箱操作。"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.java` around lines 10 - 12, 将 APICleanupVmInstanceMetadataEvent 类中的数值字段 totalCleaned 和 totalFailed 从包装类型 Integer 改为原始类型 int;在类中更新相应的字段声明以及任何与之关联的 getter/setter/constructors 或序列化使用点(例如 getTotalCleaned, setTotalCleaned, getTotalFailed, setTotalFailed)以匹配原始类型,确保没有对 null 的依赖并移除不必要的装箱/拆箱操作;保留 failedVmUuids 为 List<String> 不变并运行编译/测试以验证更改。storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java (1)
1863-1869: 建议增加psType的 null 检查。如果主存储在 API 调用期间被删除,
psType查询可能返回 null,传递给getExtensionFromMap可能导致意外行为。♻️ 建议的修改
String psType = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.type).eq(PrimaryStorageVO_.uuid, msg.getPrimaryStorageUuid()).findValue(); + if (psType == null) { + reply.setError(Platform.operr("primary storage[uuid:%s] not found", msg.getPrimaryStorageUuid())); + bus.reply(msg, reply); + return; + } VmMetadataPathBuildExtensionPoint ext = pluginRgty.getExtensionFromMap(psType, VmMetadataPathBuildExtensionPoint.class);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java` around lines 1863 - 1869, The code assumes psType (result of Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.type).eq(PrimaryStorageVO_.uuid, msg.getPrimaryStorageUuid()).findValue()) is non-null before calling pluginRgty.getExtensionFromMap; add a null check for psType and return an error via reply (similar to the existing path) if it is null to avoid passing null into getExtensionFromMap and to handle the case where the primary storage was deleted during the API call; use the same reply/Platform.operr and bus.reply(msg, reply) pattern so callers receive a clear error.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.java`:
- Around line 18-20: The setter
APIScanVmInstanceMetadataFromPrimaryStorageReply.setVmInstanceMetadata should be
null-safe like its counterpart in ScanVmInstanceMetadataFromPrimaryStorageReply:
add a null check for the vmInstanceMetadata parameter and if it's null assign an
empty list (e.g. Collections.emptyList() or new ArrayList<>()) to the field
vmInstanceMetadata, otherwise assign the provided list; update imports if
needed.
In `@header/src/main/java/org/zstack/header/vm/cdrom/APIUpdateVmCdRomMsg.java`:
- Line 9: APIUpdateVmCdRomMsg imports MetadataImpact but doesn't use it; either
remove the unused import or add the `@MetadataImpact` annotation to the
APIUpdateVmCdRomMsg class. Locate the class declaration for APIUpdateVmCdRomMsg
and either (a) delete the import line for MetadataImpact if metadata impact is
irrelevant, or (b) annotate the class with `@MetadataImpact` (matching patterns
used in APISetVmHostnameMsg/APIAttachIsoToVmInstanceMsg) to declare its metadata
impact.
In
`@header/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.java`:
- Around line 9-24: PathReplacementResult.metadataToCurrentPathMap can be null
because it's not initialized; update PathReplacementResult so callers never get
null from getMetadataToCurrentPathMap by either initializing
metadataToCurrentPathMap at declaration to an empty Map or by changing
getMetadataToCurrentPathMap() to return Collections.emptyMap()/new HashMap<>()
when the field is null; keep setMetadataToCurrentPathMap(Map) behavior intact
and ensure any callers that expect mutability receive a mutable map if you
return an empty one.
In `@header/src/main/java/org/zstack/header/vm/VmInstanceState.java`:
- Line 34: Registering 状态被加入了 offlineStates 但缺少 Registering.transactions(...)
的迁移定义,导致在调用 nextState(event) 时抛出 CloudRuntimeException;请为 Registering
添加与其他离线状态(例如 Crashed、Created)一致的 Transaction 初始化块,明确从 Registering
在接收哪些事件时转到哪些目标状态(或保持自身/终止),使用 Registering.transactions(...)
语法补齐所有必要的状态->事件->目标映射,确保事件驱动转换不会缺失分支。
In
`@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.java`:
- Around line 3903-3908: In LocalStorageKvmBackend where
httpCall(SCAN_VM_METADATA_PATH, hostUuid, cmd, ScanVmMetadataRsp.class, ...)
handles the response, guard against rsp.metadataEntries being null before
calling forEach and before setting it on
ScanVmInstanceMetadataFromPrimaryStorageReply; if metadataEntries is null or
missing from ScanVmMetadataRsp, replace it with Collections.emptyList() (or new
ArrayList<>()) and then call entry.setHostUuid(hostUuid) and
reply.setVmInstanceMetadata(...) so the agent returning null results in an empty
list instead of an NPE.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java`:
- Around line 1986-2001: Current logic picks backend via getUsableBackend() then
picks an arbitrary connected host via
factory.getConnectedHostForOperation(getSelfInventory()).get(0), which can
mismatch backend implementation when the same NFS is attached to multiple
hypervisor-clusters; change the order to pick the host first (use
factory.getConnectedHostForOperation(getSelfInventory()), select the hostUuid)
and then resolve the backend that corresponds to that host (e.g. find the
NfsPrimaryStorageBackend whose cluster/host mapping matches the selected
hostUuid or provide a helper like getBackendForHost(hostUuid)) before calling
backend.handle(...). Apply the same host-first then backend resolution change to
the other three handlers mentioned (the blocks around lines 2019–2034,
2052–2067, 2084–2099) so backend implementations always match the chosen host.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java`:
- Around line 2156-2160: 在 NfsPrimaryStorageKVMBackend 中这段使用
rsp.metadataEntries.forEach(...) 的代码存在空指针风险:在访问 rsp.metadataEntries 之前先做 null
检查并在为空时处理(例如把 r.setVmInstanceMetadata(Collections.emptyList()) 或新的空列表赋给 r),否则直接
forEach 会抛 NPE;如果不为空,再用 forEach 或流给每个 entry 设置 hostUuid 并将非空列表传给
r.setVmInstanceMetadata(...),最后调用 completion.success(r)。
---
Nitpick comments:
In `@compute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.java`:
- Around line 63-68: The code obtains psType via
Q.New(PrimaryStorageVO.class)...findValue() and immediately passes it to
pluginRgty.getExtensionFromMap; add a null check for psType after the query
(before calling pluginRgty.getExtensionFromMap) and if psType is null, call
trigger.next() and return (optionally log a debug/warn mentioning missing
PrimaryStorageVO), so getExtensionFromMap is only invoked with a non-null
psType; reference symbols: psType, Q.New(PrimaryStorageVO.class)...findValue(),
pluginRgty.getExtensionFromMap(..., VmMetadataPathBuildExtensionPoint.class),
and trigger.next().
In `@compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java`:
- Line 140: 为 VM_METADATA_LAST_REFRESH_VERSION 添加显式默认值与校验:在 VmGlobalConfig
中对静态常量 VM_METADATA_LAST_REFRESH_VERSION 设置一个合理默认(例如 "0")并在 GlobalConfig
或配置注册处添加校验回调/规则,确保值为非负整数(>=0),在解析/设置时拒绝或纠正非法值并记录错误。定位符:VM_METADATA_LAST_REFRESH_VERSION、VmGlobalConfig、GlobalConfig,修改时把默认值注入并为该项注册非负数字校验逻辑(或抛出/回退到默认)。
In
`@header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.java`:
- Around line 22-25:
APIScanVmInstanceMetadataFromPrimaryStorageReply.__example__()
目前返回空对象,需填充示例数据以改善文档;在该方法内构造一个或多个示例 VmInstanceMetadataInventory(可调用
VmInstanceMetadataInventory.__example__() 或手动设置关键字段),通过
reply.setInventories(...) 将示例列表放入回复,并设置 reply.setTotal(...)
或其他相关元数据字段以反映示例数量,确保返回的示例包含典型字段(如 vmUuid、hostUuid、path 等)以便生成更有意义的 API 文档。
In
`@header/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.java`:
- Around line 3-14: Add a clear toString() implementation to the
VmMetadataScanEntry class that returns a readable representation of all fields
(vmUuid, vmName, vmCategory, architecture, schemaVersion, metadataPath,
hostUuid, sizeBytes, lastUpdateTime, incomplete) for logging and API/debug
output; additionally implement equals(Object) and hashCode() based on the same
identifying fields (at minimum vmUuid and metadataPath or choose all fields
consistently) so instances can be compared and used in collections reliably, and
ensure both methods are placed in VmMetadataScanEntry alongside existing
getters/setters.
In `@header/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.java`:
- Around line 17-18: The uuid field in APIDeleteVmSshKeyMsg lacks the `@APIParam`
annotation used elsewhere; update the APIDeleteVmSshKeyMsg class by annotating
the private String uuid field with `@APIParam`(resourceType = VmInstanceVO.class)
(and add any missing imports for APIParam and VmInstanceVO) so the framework can
perform resource validation consistent with APISetVmSshKeyMsg.
In `@header/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.java`:
- Around line 23-24: Rename the member field SshKey to lowerCamelCase sshKey in
class APISetVmSshKeyMsg; update all usages and references to this field
(including any getters/setters, constructors, builders, JSON/serialization
annotations, and unit tests) so they refer to sshKey consistently, and ensure
the public accessor methods remain correct (getSshKey/setSshKey or adjust if you
rename them) to preserve API compatibility; run tests to verify no breakage.
In
`@header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.java`:
- Around line 10-12: 将 APICleanupVmInstanceMetadataEvent 类中的数值字段 totalCleaned 和
totalFailed 从包装类型 Integer 改为原始类型 int;在类中更新相应的字段声明以及任何与之关联的
getter/setter/constructors 或序列化使用点(例如 getTotalCleaned, setTotalCleaned,
getTotalFailed, setTotalFailed)以匹配原始类型,确保没有对 null 的依赖并移除不必要的装箱/拆箱操作;保留
failedVmUuids 为 List<String> 不变并运行编译/测试以验证更改。
In
`@header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.java`:
- Around line 10-17: The REST path should express the resource hierarchy by
moving the vm instance uuid into the URL instead of a query parameter: update
the `@RestRequest` path on class APIGetVmInstanceMetadataFromPrimaryStorageMsg to
use a path parameter (e.g. "/vm-instances/{uuid}/primary-storage-metadata" or
"/primary-storage/{primaryStorageUuid}/vm-instances/{uuid}/metadata") and ensure
the private String uuid field is declared/annotated to bind from the path (keep
`@APIParam`(resourceType = VmInstanceVO.class) and mark it required if applicable)
so the framework maps the path variable to the uuid field; adjust any consumers
that construct the URL to pass uuid in the path.
In
`@header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.java`:
- Line 28: The method signature markDirty(String vmInstanceUuid, boolean
storageStructureChange) uses a boolean flag that hurts readability; refactor by
replacing the boolean with a more descriptive API—either add separate methods
such as markDirtyForStorageStructureChange(String vmInstanceUuid) and
markDirtyForRuntimeChange(String vmInstanceUuid) or introduce an enum (e.g.,
DirtyReason { STORAGE_STRUCTURE_CHANGE, RUNTIME_CHANGE }) and change the
signature to markDirty(String vmInstanceUuid, DirtyReason reason); update
implementations of VmMetadataDirtyService and all callers to use the new
method(s) and remove the boolean overload.
In
`@header/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.java`:
- Around line 6-10: 为接口 VmMetadataResourcePersistExtensionPoint 的方法补充简明
Javadoc:在 getPrimaryStorageType(), afterVolumePersist(String primaryStorageUuid,
String resourceUuid, String resourceType, String hostUuid, long size, Timestamp
now) 和 afterSnapshotPersist(...) 上分别加入方法注释,明确说明返回值语义(getPrimaryStorageType
返回的存储类型标识),以及每个参数含义,尤其注明 resourceType 的取值范围/语义(例如是 Volume/Snapshot/其它资源类型)和 now
表示的时间语义(例如为持久化时间或事件时间,时区/精度要求);同时确保接口方法不使用多余修饰符(保持默认可见性)。
In
`@header/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.java`:
- Around line 19-21: Unify the non-null contract for list-returning resolvers in
VmUuidFromApiResolver: either update the JavaDoc of resolveVmUuids (and any
other list-returning methods in the interface) to state that null is allowed and
will be ignored, or enforce a non-null contract by changing implementations and
the JavaDoc to require returning an empty list instead of null; locate
resolveVmUuids and other list-returning methods in the VmUuidFromApiResolver
interface, update their Javadoc to match the chosen contract, and if you choose
the non-null option, update all implementations to return
Collections.emptyList() (or equivalent) instead of null.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java`:
- Around line 29-45: buildMetadataDir and buildVmMetadataPath duplicate the same
DB query to get mountPath; extract a private helper like getMountPath(String
primaryStorageUuid) that performs
Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.mountPath).eq(PrimaryStorageVO_.uuid,
primaryStorageUuid).findValue(), throws the same CloudRuntimeException when
null, and then call this helper from both buildMetadataDir and
buildVmMetadataPath to remove the duplicated query logic.
- Around line 87-99: Extract the hard-coded path markers in extractOldPrefix
into class-level constants to avoid magic strings: introduce a private static
final String[] OLD_PATH_MARKERS (or individual constants like OLD_ROOT_VOLUMES =
"/rootVolumes/" etc.) in NfsVmMetadataExtension and replace the local markers
array in extractOldPrefix to reference these constants; ensure the behavior and
ordering remain the same and update any javadoc/comments to reflect the new
constants.
In `@sdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.java`:
- Line 3: 在 RegisterVmInstanceFromMetadataResult 类中移除对同一包 org.zstack.sdk 下的
VmInstanceInventory 的冗余导入声明(去掉 import org.zstack.sdk.VmInstanceInventory;),因为
VmInstanceInventory 与 RegisterVmInstanceFromMetadataResult
位于同一包中无需显式导入;确认类中不再存在对该导入行的依赖(若有,保留直接引用类型名即可)。
In `@storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java`:
- Around line 1863-1869: The code assumes psType (result of
Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.type).eq(PrimaryStorageVO_.uuid,
msg.getPrimaryStorageUuid()).findValue()) is non-null before calling
pluginRgty.getExtensionFromMap; add a null check for psType and return an error
via reply (similar to the existing path) if it is null to avoid passing null
into getExtensionFromMap and to handle the case where the primary storage was
deleted during the API call; use the same reply/Platform.operr and
bus.reply(msg, reply) pattern so callers receive a clear error.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: cb768216-fb92-4169-ba92-aa7c25346302
⛔ Files ignored due to path filters (5)
conf/globalConfig/vm.xmlis excluded by!**/*.xmlconf/persistence.xmlis excluded by!**/*.xmlconf/serviceConfig/primaryStorage.xmlis excluded by!**/*.xmlconf/serviceConfig/vmInstance.xmlis excluded by!**/*.xmlconf/springConfigXml/VmInstanceManager.xmlis excluded by!**/*.xml
📒 Files selected for processing (149)
compute/src/main/java/org/zstack/compute/vm/CleanupVmInstanceMetadataOnPrimaryStorageGC.javacompute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.javacompute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.javacompute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.javacompute/src/main/java/org/zstack/compute/vm/VmSystemTags.javaconf/db/upgrade/V5.0.0__schema.sqlheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataReply.javaheader/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIDeleteVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIRevertVolumeFromSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIShrinkVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIUpdateVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIDeleteVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIRevertVmFromSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIUngroupVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIUpdateVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/tag/APICreateSystemTagMsg.javaheader/src/main/java/org/zstack/header/tag/APICreateSystemTagsMsg.javaheader/src/main/java/org/zstack/header/tag/APIDeleteTagMsg.javaheader/src/main/java/org/zstack/header/tag/APIUpdateSystemTagMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachIsoToVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachL3NetworkToVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachVmNicToVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeInstanceOfferingMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeVmNicNetworkMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeVmNicStateMsg.javaheader/src/main/java/org/zstack/header/vm/APIConvertTemplatedVmInstanceToVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIConvertVmInstanceToTemplatedVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APICreateVmNicMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmBootModeMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmConsolePasswordMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmHostnameMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmNicMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmStaticIpMsg.javaheader/src/main/java/org/zstack/header/vm/APIDestroyVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIDetachIsoFromVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIDetachL3NetworkFromVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIExpungeVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIMigrateVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIRecoverVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIReimageVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootModeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootOrderMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootVolumeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmClockTrackMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmConsolePasswordMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmHostnameMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmQxlMemoryMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmSoundTypeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmStaticIpMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmNicDriverMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmPriorityMsg.javaheader/src/main/java/org/zstack/header/vm/VmInstanceState.javaheader/src/main/java/org/zstack/header/vm/cdrom/APICreateVmCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/cdrom/APISetVmInstanceDefaultCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/cdrom/APIUpdateVmCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/MetadataImpact.javaheader/src/main/java/org/zstack/header/vm/metadata/ResourceMetadata.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataReply.javaheader/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataConstants.javaheader/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataDTO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataCategory.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO_.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataErrors.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathBuildExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.javaheader/src/main/java/org/zstack/header/vm/metadata/VolumeResourceMetadata.javaheader/src/main/java/org/zstack/header/volume/APIAttachDataVolumeToVmMsg.javaheader/src/main/java/org/zstack/header/volume/APIChangeVolumeStateMsg.javaheader/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/volume/APIDeleteDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIDetachDataVolumeFromVmMsg.javaheader/src/main/java/org/zstack/header/volume/APIExpungeDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIFlattenVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIRecoverDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APISyncVolumeSizeMsg.javaheader/src/main/java/org/zstack/header/volume/APIUndoSnapshotCreationMsg.javaheader/src/main/java/org/zstack/header/volume/APIUpdateVolumeMsg.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/APILocalStorageMigrateVolumeMsg.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageHypervisorBackend.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulator.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulatorConfig.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageBackend.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackendCommands.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.javaresourceconfig/src/main/java/org/zstack/resourceconfig/APIDeleteResourceConfigMsg.javaresourceconfig/src/main/java/org/zstack/resourceconfig/APIUpdateResourceConfigMsg.javasdk/src/main/java/SourceClassMap.javasdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataAction.javasdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataResult.javasdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageAction.javasdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageResult.javasdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataAction.javasdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.javasdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageAction.javasdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageResult.javasdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataAction.javasdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataResult.javasdk/src/main/java/org/zstack/sdk/VmMetadataScanEntry.javastorage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.javatestlib/src/main/java/org/zstack/testlib/ApiHelper.groovytestlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovytestlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy
| public void setVmInstanceMetadata(List<VmMetadataScanEntry> vmInstanceMetadata) { | ||
| this.vmInstanceMetadata = vmInstanceMetadata; | ||
| } |
There was a problem hiding this comment.
setVmInstanceMetadata 方法缺少 null 安全检查
与 ScanVmInstanceMetadataFromPrimaryStorageReply 类中的同名方法不一致。建议添加 null 安全检查以保持一致性并防止潜在的 NPE。
🛡️ 建议的修复
public void setVmInstanceMetadata(List<VmMetadataScanEntry> vmInstanceMetadata) {
- this.vmInstanceMetadata = vmInstanceMetadata;
+ this.vmInstanceMetadata = vmInstanceMetadata == null ? new ArrayList<>() : vmInstanceMetadata;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public void setVmInstanceMetadata(List<VmMetadataScanEntry> vmInstanceMetadata) { | |
| this.vmInstanceMetadata = vmInstanceMetadata; | |
| } | |
| public void setVmInstanceMetadata(List<VmMetadataScanEntry> vmInstanceMetadata) { | |
| this.vmInstanceMetadata = vmInstanceMetadata == null ? new ArrayList<>() : vmInstanceMetadata; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.java`
around lines 18 - 20, The setter
APIScanVmInstanceMetadataFromPrimaryStorageReply.setVmInstanceMetadata should be
null-safe like its counterpart in ScanVmInstanceMetadataFromPrimaryStorageReply:
add a null check for the vmInstanceMetadata parameter and if it's null assign an
empty list (e.g. Collections.emptyList() or new ArrayList<>()) to the field
vmInstanceMetadata, otherwise assign the provided list; update imports if
needed.
| import org.zstack.header.rest.APINoSee; | ||
| import org.zstack.header.rest.RestRequest; | ||
| import org.zstack.header.vm.VmInstanceMessage; | ||
| import org.zstack.header.vm.metadata.MetadataImpact; |
There was a problem hiding this comment.
未使用的导入:MetadataImpact 已导入但未应用注解。
此文件导入了 MetadataImpact,但类上并未添加 @MetadataImpact 注解。对比本 PR 中其他类似的 API 消息类(如 APISetVmHostnameMsg、APIAttachIsoToVmInstanceMsg),它们都同时添加了导入和注解。
请确认这是有意为之还是遗漏了注解。如果 APIUpdateVmCdRomMsg 需要声明元数据影响,建议补充相应的 @MetadataImpact 注解。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@header/src/main/java/org/zstack/header/vm/cdrom/APIUpdateVmCdRomMsg.java` at
line 9, APIUpdateVmCdRomMsg imports MetadataImpact but doesn't use it; either
remove the unused import or add the `@MetadataImpact` annotation to the
APIUpdateVmCdRomMsg class. Locate the class declaration for APIUpdateVmCdRomMsg
and either (a) delete the import line for MetadataImpact if metadata impact is
irrelevant, or (b) annotate the class with `@MetadataImpact` (matching patterns
used in APISetVmHostnameMsg/APIAttachIsoToVmInstanceMsg) to declare its metadata
impact.
| class PathReplacementResult { | ||
| /** metadata path → current path 完整映射 */ | ||
| private Map<String, String> metadataToCurrentPathMap; | ||
| private String oldPrefix; | ||
| private String newPrefix; | ||
|
|
||
| public PathReplacementResult() { | ||
| } | ||
|
|
||
| public Map<String, String> getMetadataToCurrentPathMap() { | ||
| return metadataToCurrentPathMap; | ||
| } | ||
|
|
||
| public void setMetadataToCurrentPathMap(Map<String, String> metadataToCurrentPathMap) { | ||
| this.metadataToCurrentPathMap = metadataToCurrentPathMap; | ||
| } |
There was a problem hiding this comment.
PathReplacementResult.metadataToCurrentPathMap 可能返回 null
metadataToCurrentPathMap 字段没有初始化,如果调用者在未设置值的情况下调用 getMetadataToCurrentPathMap(),会返回 null,可能导致后续 NPE。
建议在声明时初始化或在 getter 中返回空 Map。
🛡️ 建议的修复方案
class PathReplacementResult {
/** metadata path → current path 完整映射 */
- private Map<String, String> metadataToCurrentPathMap;
+ private Map<String, String> metadataToCurrentPathMap = new LinkedHashMap<>();
private String oldPrefix;
private String newPrefix;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| class PathReplacementResult { | |
| /** metadata path → current path 完整映射 */ | |
| private Map<String, String> metadataToCurrentPathMap; | |
| private String oldPrefix; | |
| private String newPrefix; | |
| public PathReplacementResult() { | |
| } | |
| public Map<String, String> getMetadataToCurrentPathMap() { | |
| return metadataToCurrentPathMap; | |
| } | |
| public void setMetadataToCurrentPathMap(Map<String, String> metadataToCurrentPathMap) { | |
| this.metadataToCurrentPathMap = metadataToCurrentPathMap; | |
| } | |
| class PathReplacementResult { | |
| /** metadata path → current path 完整映射 */ | |
| private Map<String, String> metadataToCurrentPathMap = new LinkedHashMap<>(); | |
| private String oldPrefix; | |
| private String newPrefix; | |
| public PathReplacementResult() { | |
| } | |
| public Map<String, String> getMetadataToCurrentPathMap() { | |
| return metadataToCurrentPathMap; | |
| } | |
| public void setMetadataToCurrentPathMap(Map<String, String> metadataToCurrentPathMap) { | |
| this.metadataToCurrentPathMap = metadataToCurrentPathMap; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@header/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.java`
around lines 9 - 24, PathReplacementResult.metadataToCurrentPathMap can be null
because it's not initialized; update PathReplacementResult so callers never get
null from getMetadataToCurrentPathMap by either initializing
metadataToCurrentPathMap at declaration to an empty Map or by changing
getMetadataToCurrentPathMap() to return Collections.emptyMap()/new HashMap<>()
when the field is null; keep setMetadataToCurrentPathMap(Map) behavior intact
and ensure any callers that expect mutability receive a mutable map if you
return an empty one.
| Unknown(VmInstanceStateEvent.unknown), | ||
| Crashed(VmInstanceStateEvent.crashed); | ||
| Crashed(VmInstanceStateEvent.crashed), | ||
| Registering(null); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 1) 确认 Registering 是否配置了状态迁移
rg -n "Registering\\.transactions\\(" --type=java
# 2) 查看 Registering 的使用点,确认是否会进入事件驱动状态迁移
rg -n "VmInstanceState\\.Registering|setState\\(.*Registering|changeState\\(.*Registering" -C 3 --type=java
# 3) 查看状态机 nextState 的调用点,评估 Registering 是否会经过 nextState(event)
rg -n "\\.nextState\\(" -C 3 --type=javaRepository: MatheMatrix/zstack
Length of output: 9779
🏁 Script executed:
cat -n header/src/main/java/org/zstack/header/vm/VmInstanceState.java | head -300Repository: MatheMatrix/zstack
Length of output: 15781
🏁 Script executed:
# Check how Registering is used in VM-related code
rg -n "VmInstanceState\.Registering|state.*Registering|setState.*Registering" -C 3 --type=java compute/
# Check if offlineStates is used specially to bypass nextState
rg -n "offlineStates\." -C 3 --type=java header/Repository: MatheMatrix/zstack
Length of output: 1304
🏁 Script executed:
# Search for Registering usage across entire codebase
rg -n "Registering" --type=java | head -50
# Also check for state change patterns that might use Registering
rg -n "changeVmState|setState.*Vm" compute/src/main/java/org/zstack/compute/vm/ --type=java | head -30Repository: MatheMatrix/zstack
Length of output: 4750
🏁 Script executed:
# Check if Registering is used anywhere in message handlers or state initialization
rg -n "setState.*Registering|setStateInDb.*Registering|=.*Registering" --type=java
# Check Error state to see if it also lacks transactions (seems to be the only other state with null parameter)
rg -n "Error\.transactions" --type=java
# Check if there are any recent commits or uses of Registering state
git log --all --oneline --grep="Registering" 2>/dev/null | head -10
</parameter>Repository: MatheMatrix/zstack
Length of output: 167
🏁 Script executed:
# Check if Registering is used anywhere in message handlers or state initialization
rg -n "setState.*Registering|setStateInDb.*Registering|=.*Registering" --type=java
# Check Error state to see if it also lacks transactions (seems to be the only other state with null parameter)
rg -n "Error\.transactions" --type=java
# Check if there are any recent commits or uses of Registering state
git log --all --oneline --grep="Registering" 2>/dev/null | head -10Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# Check when Registering was added to the file
git log -p --all -- header/src/main/java/org/zstack/header/vm/VmInstanceState.java | grep -A 5 -B 5 "Registering" | head -40
# Check if Error state usage patterns (since it also has null parameter and no transactions)
rg -n "VmInstanceState\.Error" --type=java | head -20
# Look for any TODOs or comments about Registering
rg -n "Registering|TODO|FIXME" header/src/main/java/org/zstack/header/vm/VmInstanceState.javaRepository: MatheMatrix/zstack
Length of output: 130
🏁 Script executed:
# Check if offlineStates set is used for special handling that might bypass nextState
rg -n "offlineStates\.contains|offlineStates\.add" --type=java -B 2 -A 2
# Verify the complete picture: check Crashed state transactions as a reference offline state
sed -n '183,193p' header/src/main/java/org/zstack/header/vm/VmInstanceState.java
# Check if there's a registration or initialization code that uses Registering state
rg -n "register|Register" compute/src/main/java/org/zstack/compute/vm/VmInstanceManagerImpl.java | head -20Repository: MatheMatrix/zstack
Length of output: 2528
Registering 状态缺少状态迁移配置,需要补充,否则在事件驱动时会抛出异常。
新增的 Registering 状态(第 34 行)被添加到 offlineStates 集合(第 56 行),但缺少对应的 Registering.transactions(...) 初始化块。相比之下,其他离线状态如 Crashed 和 Created 都定义了完整的状态迁移映射。当状态机在 Registering 状态调用 nextState(event) 方法时,会在第 237-238 行抛出 CloudRuntimeException。
需要根据业务需求补充 Registering 的有效状态迁移。如果 Registering 是确实需要参与事件驱动转换的中间或终止状态,应参考 Crashed 的模式补充对应的 Transaction 定义。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@header/src/main/java/org/zstack/header/vm/VmInstanceState.java` at line 34,
Registering 状态被加入了 offlineStates 但缺少 Registering.transactions(...) 的迁移定义,导致在调用
nextState(event) 时抛出 CloudRuntimeException;请为 Registering 添加与其他离线状态(例如
Crashed、Created)一致的 Transaction 初始化块,明确从 Registering
在接收哪些事件时转到哪些目标状态(或保持自身/终止),使用 Registering.transactions(...)
语法补齐所有必要的状态->事件->目标映射,确保事件驱动转换不会缺失分支。
|
|
||
| ScanVmInstanceMetadataFromPrimaryStorageReply r = new ScanVmInstanceMetadataFromPrimaryStorageReply(); | ||
| rsp.metadataEntries.forEach(entry -> entry.setHostUuid(hostUuid)); | ||
| r.setVmInstanceMetadata(rsp.metadataEntries); | ||
| completion.success(r); |
There was a problem hiding this comment.
潜在的空指针异常风险
rsp.metadataEntries 在调用 forEach 之前未进行空检查。如果 agent 返回空列表或 null,这里会抛出 NPE。
🛡️ 建议添加空值检查
ScanVmInstanceMetadataFromPrimaryStorageReply r = new ScanVmInstanceMetadataFromPrimaryStorageReply();
-rsp.metadataEntries.forEach(entry -> entry.setHostUuid(hostUuid));
-r.setVmInstanceMetadata(rsp.metadataEntries);
+if (rsp.metadataEntries != null) {
+ rsp.metadataEntries.forEach(entry -> entry.setHostUuid(hostUuid));
+ r.setVmInstanceMetadata(rsp.metadataEntries);
+} else {
+ r.setVmInstanceMetadata(Collections.emptyList());
+}
completion.success(r);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java`
around lines 2156 - 2160, 在 NfsPrimaryStorageKVMBackend 中这段使用
rsp.metadataEntries.forEach(...) 的代码存在空指针风险:在访问 rsp.metadataEntries 之前先做 null
检查并在为空时处理(例如把 r.setVmInstanceMetadata(Collections.emptyList()) 或新的空列表赋给 r),否则直接
forEach 会抛 NPE;如果不为空,再用 forEach 或流给每个 entry 设置 hostUuid 并将非空列表传给
r.setVmInstanceMetadata(...),最后调用 completion.success(r)。
8b89d8b to
8dbbbf3
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.java (1)
933-990:⚠️ Potential issue | 🔴 Critical同步更新 LocalStorageSimulator 的协议。
这里新增/调整了 agent 协议,但
plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulator.java:337-368仍在SCAN_VM_METADATA_PATH上调用旧的rsp.setMetadata(...),而且没有为PREFIX_REBASE_BACKING_FILES_PATH注册 handler。按当前代码,simulator 端要么编译不过,要么在 rebase 流程里直接落到未注册路径。💡 建议同步的模拟器改动
`@RequestMapping`(value=LocalStorageKvmBackend.SCAN_VM_METADATA_PATH, method= RequestMethod.POST) public HttpEntity handle(ScanVmMetadataCmd cmd) { - ScanVmMetadataRsp rsp = new ScanVmMetadataRsp(); - rsp.setMetadata(new HashMap<>()); - return new HttpEntity(JSONObjectUtil.toJsonString(rsp)); + return new HttpEntity(JSONObjectUtil.toJsonString(new ScanVmMetadataRsp())); } + +@RequestMapping(value=LocalStorageKvmBackend.PREFIX_REBASE_BACKING_FILES_PATH, method= RequestMethod.POST) +public HttpEntity handle(PrefixRebaseBackingFilesCmd cmd) { + return new HttpEntity(JSONObjectUtil.toJsonString(new PrefixRebaseBackingFilesRsp())); +}Also applies to: 3943-3954
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.java` around lines 933 - 990, The simulator still uses the old response API and is missing a handler: in LocalStorageSimulator update the SCAN_VM_METADATA_PATH response code to populate the new ScanVmMetadataRsp.metadataEntries list instead of calling rsp.setMetadata(...), and add/register a handler for PREFIX_REBASE_BACKING_FILES_PATH that returns a PrefixRebaseBackingFilesRsp (set rebasedCount appropriately); ensure you use the exact classes/constants ScanVmMetadataRsp, PrefixRebaseBackingFilesCmd/PrefixRebaseBackingFilesRsp, SCAN_VM_METADATA_PATH and PREFIX_REBASE_BACKING_FILES_PATH so the simulator compiles and the rebase flow hits a registered path.
🤖 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/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java`:
- Around line 1983-2004: The handlers currently force-choose the first connected
host (via factory.getConnectedHostForOperation and connectedHosts.get(0)) and
call getBackendByHostUuid(hostUuid), which overrides any hostUuid already set by
the caller on messages like GetVmInstanceMetadataFromPrimaryStorageMsg (and
similarly in CleanupVmInstanceMetadataOnPrimaryStorageMsg and
RebaseVolumeBackingFileOnPrimaryStorageMsg handlers). Change each handler to
prefer the incoming msg.getHostUuid() when non-null/non-empty, and only if that
is missing fall back to selecting a connected host from
factory.getConnectedHostForOperation(getSelfInventory()) (and then call
getBackendByHostUuid with that resolved hostUuid); keep the existing
ReturnValueCompletion logic and error reply behavior unchanged.
In `@storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java`:
- Around line 1884-1888: The code assumes re.getVmInstanceMetadata() is non-null
before calling stream(), causing NPEs when a backend returns null; update the
logic in PrimaryStorageBase around the
ScanVmInstanceMetadataFromPrimaryStorageReply handling (variable re) to
defensively handle null by treating getVmInstanceMetadata() as an empty list
before filtering for VmMetadataCategory.TEMPLATE_CACHE and then call
reply.setVmInstanceMetadata(filtered) with that safe list (use a
null-coalescing/empty-list pattern or Optional to normalize
re.getVmInstanceMetadata() to Collections.emptyList()).
---
Outside diff comments:
In
`@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.java`:
- Around line 933-990: The simulator still uses the old response API and is
missing a handler: in LocalStorageSimulator update the SCAN_VM_METADATA_PATH
response code to populate the new ScanVmMetadataRsp.metadataEntries list instead
of calling rsp.setMetadata(...), and add/register a handler for
PREFIX_REBASE_BACKING_FILES_PATH that returns a PrefixRebaseBackingFilesRsp (set
rebasedCount appropriately); ensure you use the exact classes/constants
ScanVmMetadataRsp, PrefixRebaseBackingFilesCmd/PrefixRebaseBackingFilesRsp,
SCAN_VM_METADATA_PATH and PREFIX_REBASE_BACKING_FILES_PATH so the simulator
compiles and the rebase flow hits a registered path.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 149730dc-fa07-4b2d-b228-7f41fd31a4ef
⛔ Files ignored due to path filters (5)
conf/globalConfig/vm.xmlis excluded by!**/*.xmlconf/persistence.xmlis excluded by!**/*.xmlconf/serviceConfig/primaryStorage.xmlis excluded by!**/*.xmlconf/serviceConfig/vmInstance.xmlis excluded by!**/*.xmlconf/springConfigXml/VmInstanceManager.xmlis excluded by!**/*.xml
📒 Files selected for processing (148)
compute/src/main/java/org/zstack/compute/vm/CleanupVmInstanceMetadataOnPrimaryStorageGC.javacompute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.javacompute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.javacompute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.javacompute/src/main/java/org/zstack/compute/vm/VmSystemTags.javaconf/db/upgrade/V5.0.0__schema.sqlheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataReply.javaheader/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIDeleteVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIRevertVolumeFromSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIShrinkVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIUpdateVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIDeleteVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIRevertVmFromSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIUngroupVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIUpdateVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/tag/APICreateSystemTagMsg.javaheader/src/main/java/org/zstack/header/tag/APICreateSystemTagsMsg.javaheader/src/main/java/org/zstack/header/tag/APIDeleteTagMsg.javaheader/src/main/java/org/zstack/header/tag/APIUpdateSystemTagMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachIsoToVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachL3NetworkToVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachVmNicToVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeInstanceOfferingMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeVmNicNetworkMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeVmNicStateMsg.javaheader/src/main/java/org/zstack/header/vm/APIConvertTemplatedVmInstanceToVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIConvertVmInstanceToTemplatedVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APICreateVmNicMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmBootModeMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmConsolePasswordMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmHostnameMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmNicMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmStaticIpMsg.javaheader/src/main/java/org/zstack/header/vm/APIDestroyVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIDetachIsoFromVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIDetachL3NetworkFromVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIExpungeVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIMigrateVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIRecoverVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIReimageVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootModeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootOrderMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootVolumeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmClockTrackMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmConsolePasswordMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmHostnameMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmQxlMemoryMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmSoundTypeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmStaticIpMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmNicDriverMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmPriorityMsg.javaheader/src/main/java/org/zstack/header/vm/VmInstanceState.javaheader/src/main/java/org/zstack/header/vm/cdrom/APICreateVmCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/cdrom/APISetVmInstanceDefaultCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/MetadataImpact.javaheader/src/main/java/org/zstack/header/vm/metadata/ResourceMetadata.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataReply.javaheader/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataConstants.javaheader/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataDTO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataCategory.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO_.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataErrors.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathBuildExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.javaheader/src/main/java/org/zstack/header/vm/metadata/VolumeResourceMetadata.javaheader/src/main/java/org/zstack/header/volume/APIAttachDataVolumeToVmMsg.javaheader/src/main/java/org/zstack/header/volume/APIChangeVolumeStateMsg.javaheader/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/volume/APIDeleteDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIDetachDataVolumeFromVmMsg.javaheader/src/main/java/org/zstack/header/volume/APIExpungeDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIFlattenVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIRecoverDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APISyncVolumeSizeMsg.javaheader/src/main/java/org/zstack/header/volume/APIUndoSnapshotCreationMsg.javaheader/src/main/java/org/zstack/header/volume/APIUpdateVolumeMsg.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/APILocalStorageMigrateVolumeMsg.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageHypervisorBackend.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulator.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulatorConfig.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageBackend.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackendCommands.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.javaresourceconfig/src/main/java/org/zstack/resourceconfig/APIDeleteResourceConfigMsg.javaresourceconfig/src/main/java/org/zstack/resourceconfig/APIUpdateResourceConfigMsg.javasdk/src/main/java/SourceClassMap.javasdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataAction.javasdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataResult.javasdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageAction.javasdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageResult.javasdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataAction.javasdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.javasdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageAction.javasdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageResult.javasdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataAction.javasdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataResult.javasdk/src/main/java/org/zstack/sdk/VmMetadataScanEntry.javastorage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.javatestlib/src/main/java/org/zstack/testlib/ApiHelper.groovytestlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovytestlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy
✅ Files skipped from review due to trivial changes (88)
- header/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/APISetVmHostnameMsg.java
- header/src/main/java/org/zstack/header/vm/cdrom/APICreateVmCdRomMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/ResourceMetadata.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootVolumeMsg.java
- header/src/main/java/org/zstack/header/volume/APIExpungeDataVolumeMsg.java
- header/src/main/java/org/zstack/header/volume/APIUpdateVolumeMsg.java
- header/src/main/java/org/zstack/header/volume/APIFlattenVolumeMsg.java
- conf/db/upgrade/V5.0.0__schema.sql
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataReply.java
- header/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIShrinkVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIUpdateVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIRevertVmFromSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIUngroupVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIUpdateVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/tag/APIDeleteTagMsg.java
- header/src/main/java/org/zstack/header/vm/APIAttachIsoToVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIConvertTemplatedVmInstanceToVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeVmNicStateMsg.java
- header/src/main/java/org/zstack/header/vm/APIConvertVmInstanceToTemplatedVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APICreateVmNicMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmBootModeMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmNicMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmStaticIpMsg.java
- header/src/main/java/org/zstack/header/vm/APIDestroyVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIMigrateVmMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootModeMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootOrderMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmConsolePasswordMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmSoundTypeMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmStaticIpMsg.java
- header/src/main/java/org/zstack/header/vm/APIUpdateVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEvent.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEventDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEventDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/MetadataImpact.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO_.java
- header/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataErrors.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathBuildExtensionPoint.java
- header/src/main/java/org/zstack/header/vm/metadata/VolumeResourceMetadata.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEvent.java
- resourceconfig/src/main/java/org/zstack/resourceconfig/APIDeleteResourceConfigMsg.java
- sdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageResult.java
- sdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageResult.java
- sdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataResult.java
- testlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovy
- header/src/main/java/org/zstack/header/vm/APIUpdateVmNicDriverMsg.java
- header/src/main/java/org/zstack/header/tag/APIUpdateSystemTagMsg.java
- sdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataCategory.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataDTO.java
- resourceconfig/src/main/java/org/zstack/resourceconfig/APIUpdateResourceConfigMsg.java
- sdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataResult.java
- sdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageAction.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovy
- sdk/src/main/java/org/zstack/sdk/VmMetadataScanEntry.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/APIAttachVmNicToVmMsg.java
- header/src/main/java/org/zstack/header/vm/APIReimageVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataReply.java
- plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java
- header/src/main/java/org/zstack/header/vm/APISetVmQxlMemoryMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeInstanceOfferingMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataConstants.java
🚧 Files skipped from review as they are similar to previous changes (40)
- header/src/main/java/org/zstack/header/vm/VmInstanceState.java
- header/src/main/java/org/zstack/header/volume/APIChangeVolumeStateMsg.java
- compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java
- compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java
- header/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIDeleteVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIRevertVolumeFromSnapshotMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIDeleteVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/tag/APICreateSystemTagMsg.java
- header/src/main/java/org/zstack/header/tag/APICreateSystemTagsMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeVmNicNetworkMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmConsolePasswordMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmHostnameMsg.java
- header/src/main/java/org/zstack/header/vm/APIDetachIsoFromVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIDetachL3NetworkFromVmMsg.java
- header/src/main/java/org/zstack/header/vm/APIExpungeVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIRecoverVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmClockTrackMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO.java
- header/src/main/java/org/zstack/header/volume/APIAttachDataVolumeToVmMsg.java
- header/src/main/java/org/zstack/header/volume/APIRecoverDataVolumeMsg.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/APILocalStorageMigrateVolumeMsg.java
- testlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy
- header/src/main/java/org/zstack/header/vm/APIAttachL3NetworkToVmMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsg.java
- sdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageAction.java
- sdk/src/main/java/SourceClassMap.java
- plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageBackend.java
- header/src/main/java/org/zstack/header/vm/cdrom/APISetVmInstanceDefaultCdRomMsg.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsg.java
- sdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataAction.java
- header/src/main/java/org/zstack/header/volume/APISyncVolumeSizeMsg.java
- header/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotGroupMsg.java
- plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEventDoc_zh_cn.groovy
| protected void handle(GetVmInstanceMetadataFromPrimaryStorageMsg msg) { | ||
| GetVmInstanceMetadataFromPrimaryStorageReply reply = new GetVmInstanceMetadataFromPrimaryStorageReply(); | ||
| List<HostInventory> connectedHosts = factory.getConnectedHostForOperation(getSelfInventory()); | ||
| if (connectedHosts.isEmpty()) { | ||
| reply.setError(operr("no connected host found for NFS primary storage[uuid:%s]", self.getUuid())); | ||
| bus.reply(msg, reply); | ||
| return; | ||
| } | ||
| String hostUuid = connectedHosts.get(0).getUuid(); | ||
| final NfsPrimaryStorageBackend backend = getBackendByHostUuid(hostUuid); | ||
| backend.handle(msg, hostUuid, new ReturnValueCompletion<GetVmInstanceMetadataFromPrimaryStorageReply>(msg) { | ||
| @Override | ||
| public void success(GetVmInstanceMetadataFromPrimaryStorageReply r) { | ||
| bus.reply(msg, r); | ||
| } | ||
|
|
||
| @Override | ||
| public void fail(ErrorCode errorCode) { | ||
| reply.setError(errorCode); | ||
| bus.reply(msg, reply); | ||
| } | ||
| }); |
There was a problem hiding this comment.
不要覆盖调用方已经指定的 hostUuid。
GetVmInstanceMetadataFromPrimaryStorageMsg、CleanupVmInstanceMetadataOnPrimaryStorageMsg 和 RebaseVolumeBackingFileOnPrimaryStorageMsg 都是按 host 路由的消息;这里固定改成第一个 connected host,会把上游已经选好的目标主机丢掉。在同一个 NFS 同时挂到多个 hypervisor 集群时,请求仍然可能被发到错误的 backend/agent。
💡 建议修正
- List<HostInventory> connectedHosts = factory.getConnectedHostForOperation(getSelfInventory());
- if (connectedHosts.isEmpty()) {
- reply.setError(operr("no connected host found for NFS primary storage[uuid:%s]", self.getUuid()));
- bus.reply(msg, reply);
- return;
- }
- String hostUuid = connectedHosts.get(0).getUuid();
+ String hostUuid = msg.getHostUuid();
+ if (hostUuid == null) {
+ List<HostInventory> connectedHosts = factory.getConnectedHostForOperation(getSelfInventory());
+ if (connectedHosts.isEmpty()) {
+ reply.setError(operr("no connected host found for NFS primary storage[uuid:%s]", self.getUuid()));
+ bus.reply(msg, reply);
+ return;
+ }
+ hostUuid = connectedHosts.get(0).getUuid();
+ }
final NfsPrimaryStorageBackend backend = getBackendByHostUuid(hostUuid);对这三个 handler 都建议沿用同样的顺序:先尊重消息里的 hostUuid,再回退到任意可用 host。
Also applies to: 2032-2054, 2057-2079
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java`
around lines 1983 - 2004, The handlers currently force-choose the first
connected host (via factory.getConnectedHostForOperation and
connectedHosts.get(0)) and call getBackendByHostUuid(hostUuid), which overrides
any hostUuid already set by the caller on messages like
GetVmInstanceMetadataFromPrimaryStorageMsg (and similarly in
CleanupVmInstanceMetadataOnPrimaryStorageMsg and
RebaseVolumeBackingFileOnPrimaryStorageMsg handlers). Change each handler to
prefer the incoming msg.getHostUuid() when non-null/non-empty, and only if that
is missing fall back to selecting a connected host from
factory.getConnectedHostForOperation(getSelfInventory()) (and then call
getBackendByHostUuid with that resolved hostUuid); keep the existing
ReturnValueCompletion logic and error reply behavior unchanged.
| ScanVmInstanceMetadataFromPrimaryStorageReply re = r.castReply(); | ||
| List<VmMetadataScanEntry> filtered = re.getVmInstanceMetadata().stream() | ||
| .filter(e -> !VmMetadataCategory.TEMPLATE_CACHE.toString().equals(e.getVmCategory())) | ||
| .collect(Collectors.toList()); | ||
| reply.setVmInstanceMetadata(filtered); |
There was a problem hiding this comment.
空扫描结果这里也要兜底。
这里直接对 re.getVmInstanceMetadata() 调 stream()。只要某个后端在“没有元数据”场景返回 null,一次正常的空扫描就会被放大成异常回复。
💡 建议修改
- List<VmMetadataScanEntry> filtered = re.getVmInstanceMetadata().stream()
+ List<VmMetadataScanEntry> filtered = Optional.ofNullable(re.getVmInstanceMetadata())
+ .orElse(Collections.emptyList())
+ .stream()
.filter(e -> !VmMetadataCategory.TEMPLATE_CACHE.toString().equals(e.getVmCategory()))
.collect(Collectors.toList());🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java`
around lines 1884 - 1888, The code assumes re.getVmInstanceMetadata() is
non-null before calling stream(), causing NPEs when a backend returns null;
update the logic in PrimaryStorageBase around the
ScanVmInstanceMetadataFromPrimaryStorageReply handling (variable re) to
defensively handle null by treating getVmInstanceMetadata() as an empty list
before filtering for VmMetadataCategory.TEMPLATE_CACHE and then call
reply.setVmInstanceMetadata(filtered) with that safe list (use a
null-coalescing/empty-list pattern or Optional to normalize
re.getVmInstanceMetadata() to Collections.emptyList()).
8dbbbf3 to
4af3960
Compare
|
Comment from yaohua.wu: Review: MR !9444 — ZSV-11559 (add MetadataImpact — zstack)总体评价这是一个架构设计良好的新功能——VM 注册元数据管理。核心思路清晰: 🔴 Critical1. [premium] // mevoco/.../APICreateVolumesSnapshotMsg.java
@MetadataImpact(value = MetadataImpact.Impact.STORAGE, resolver = "volumeUuidToVmUuid", field = "volumeUuid")
public class APICreateVolumesSnapshotMsg extends APIMessage {
private List<String> volumeUuids; // ← 实际字段是 volumeUuids(复数)注解声明 修复:改为 🟡 Warning2. [zstack+premium]
两处代码完全一样(检查 3. [premium] // mevoco/.../resolver/TagUuidToVmUuidResolver.java
private final ResourceUuidToVmUuidResolver resourceResolver = new ResourceUuidToVmUuidResolver();其他 resolver 都是 Spring bean(在 4. [premium]
建议:(1) 增加批次间 5. [zstack] // NfsPrimaryStorage.java
protected void handle(RebaseVolumeBackingFileOnPrimaryStorageMsg msg) {其他 4 个 metadata handler(Update/Get/Scan/Cleanup)都加了 6. [utility] Python agent # zstacklib/utils/file_metadata_handler.py
self._lock_map = {} # 为每个 metadataPath 创建 Lock,永不清理agent 长期运行时,随着 VM 不断创建/删除, 7. [utility] Python agent 三个插件(localstorage/nfs/shared_block)的 Response 类和 handler 方法完全重复
🟢 Suggestion8. [zstack] 9. [zstack] protected void handle(UpdateVmInstanceMetadataOnPrimaryStorageMsg msg) {
reply.setError(operr("operation not supported")); // 建议加上 PS type 和 UUID
}改为类似 10. [premium] 多管理节点场景下,两个 MN 可能同时读取相同的 11. [zstack] MetadataImpact 注解覆盖面确认 已审查 zstack 仓库 39 个 + premium 仓库 22 个 Verdict: REVISION_REQUIREDCritical #1( 🤖 Robot Reviewer |
4af3960 to
fd6171f
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (3)
plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java (1)
1983-1992:⚠️ Potential issue | 🟠 Major先用调用方传入的
hostUuid,不要无条件改选第一个 connected host。这三个 handler 现在都会覆盖上游已经选好的宿主机。NFS 同时挂到多个 cluster / hypervisor 时,请求仍可能被发到错误的 backend / agent;这里应优先使用
msg.getHostUuid(),只有缺失时再 fallback 到任意可用 host。Also applies to: 2032-2042, 2057-2066
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java` around lines 1983 - 1992, The handler currently ignores any caller-selected host and always picks connectedHosts.get(0); change it to use msg.getHostUuid() when present (e.g., if msg.getHostUuid() != null && !msg.getHostUuid().isEmpty()) as the preferred hostUuid, and only fall back to connectedHosts.get(0). Update the host selection before calling getBackendByHostUuid(hostUuid) in handle(GetVmInstanceMetadataFromPrimaryStorageMsg) (and apply the same fix to the two other handlers mentioned around lines 2032-2042 and 2057-2066) so the code uses the caller-provided hostUuid first and only uses the first connected host when msg.getHostUuid() is missing.plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java (2)
2157-2160:⚠️ Potential issue | 🟡 Minor
metadataEntries可能为null,这里会在回包路径上 NPE。只要 agent 返回
null,这里的forEach就会抛异常,扫描接口拿不到 reply。空结果请回填空列表。💡 建议兜底为空列表
ScanVmInstanceMetadataFromPrimaryStorageReply r = new ScanVmInstanceMetadataFromPrimaryStorageReply(); - rsp.metadataEntries.forEach(entry -> entry.setHostUuid(hostUuid)); - r.setVmInstanceMetadata(rsp.metadataEntries); + if (rsp.metadataEntries == null) { + r.setVmInstanceMetadata(Collections.emptyList()); + } else { + rsp.metadataEntries.forEach(entry -> entry.setHostUuid(hostUuid)); + r.setVmInstanceMetadata(rsp.metadataEntries); + } completion.success(r);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java` around lines 2157 - 2160, The reply handling assumes rsp.metadataEntries is non-null and calls forEach, which can NPE if agent returned null; before iterating and before calling r.setVmInstanceMetadata ensure a non-null list (e.g., replace null with Collections.emptyList() or new ArrayList<>()), then call entry.setHostUuid(hostUuid) on that safe list and pass it to r.setVmInstanceMetadata(...) before completion.success(r); update the block around ScanVmInstanceMetadataFromPrimaryStorageReply, rsp.metadataEntries, setHostUuid, r.setVmInstanceMetadata, and completion.success accordingly.
44-45:⚠️ Potential issue | 🔴 Critical这几个新 handler 现在会直接编译失败。
方法签名里使用了
GetVmInstanceMetadataFromPrimaryStorageMsg、GetVmInstanceMetadataFromPrimaryStorageReply、ScanVmInstanceMetadataFromPrimaryStorageMsg、ScanVmInstanceMetadataFromPrimaryStorageReply、CleanupVmInstanceMetadataOnPrimaryStorageMsg、CleanupVmInstanceMetadataOnPrimaryStorageReply的未限定类名,但 import 区只引入了UpdateVmInstanceMetadataOnPrimaryStorage*。Java 编译器会在解析这些类型时报cannot find symbol错误。💡 建议补齐 import
import org.zstack.header.vm.metadata.UpdateVmInstanceMetadataOnPrimaryStorageMsg; import org.zstack.header.vm.metadata.UpdateVmInstanceMetadataOnPrimaryStorageReply; +import org.zstack.header.vm.metadata.GetVmInstanceMetadataFromPrimaryStorageMsg; +import org.zstack.header.vm.metadata.GetVmInstanceMetadataFromPrimaryStorageReply; +import org.zstack.header.vm.metadata.ScanVmInstanceMetadataFromPrimaryStorageMsg; +import org.zstack.header.vm.metadata.ScanVmInstanceMetadataFromPrimaryStorageReply; +import org.zstack.header.vm.metadata.CleanupVmInstanceMetadataOnPrimaryStorageMsg; +import org.zstack.header.vm.metadata.CleanupVmInstanceMetadataOnPrimaryStorageReply;另外,第 2157 行对
rsp.metadataEntries的 forEach 调用缺少 null 检查,可能导致 NullPointerException。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java` around lines 44 - 45, The new handlers in NfsPrimaryStorageKVMBackend reference several metadata message/reply types that are not imported and will cause compile errors—add imports for GetVmInstanceMetadataFromPrimaryStorageMsg, GetVmInstanceMetadataFromPrimaryStorageReply, ScanVmInstanceMetadataFromPrimaryStorageMsg, ScanVmInstanceMetadataFromPrimaryStorageReply, CleanupVmInstanceMetadataOnPrimaryStorageMsg, and CleanupVmInstanceMetadataOnPrimaryStorageReply to the import block (alongside the existing UpdateVmInstanceMetadataOnPrimaryStorage* imports) so the class compiles; also guard the iteration over rsp.metadataEntries (the forEach call around line ~2157) with a null check (e.g., check rsp.metadataEntries != null before calling forEach) to avoid a possible NullPointerException.
🧹 Nitpick comments (1)
plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.java (1)
37-53: 可考虑提取 URL 查询的公共逻辑。
buildMetadataDir和buildVmMetadataPath中存在重复的 URL 查询和 null 检查代码。♻️ 建议重构
+ private String getUrlOrThrow(String primaryStorageUuid) { + String url = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.url) + .eq(PrimaryStorageVO_.uuid, primaryStorageUuid).findValue(); + if (url == null) { + throw new CloudRuntimeException(String.format("cannot find url for primary storage[uuid:%s]", primaryStorageUuid)); + } + return url; + } + `@Override` public String buildMetadataDir(String primaryStorageUuid) { - String url = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.url).eq(PrimaryStorageVO_.uuid, primaryStorageUuid).findValue(); - if (url == null) { - throw new CloudRuntimeException(String.format("cannot find url for primary storage[uuid:%s]", primaryStorageUuid)); - } + String url = getUrlOrThrow(primaryStorageUuid); return String.format("%s/%s", normalizeBaseDir(url), VmInstanceMetadataConstants.METADATA_DIR_NAME); } `@Override` public String buildVmMetadataPath(String primaryStorageUuid, String vmInstanceUuid) { - String url = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.url).eq(PrimaryStorageVO_.uuid, primaryStorageUuid).findValue(); - if (url == null) { - throw new CloudRuntimeException(String.format("cannot find url for primary storage[uuid:%s]", primaryStorageUuid)); - } + String url = getUrlOrThrow(primaryStorageUuid); return String.format("%s/%s/%s%s", normalizeBaseDir(url), VmInstanceMetadataConstants.METADATA_DIR_NAME, vmInstanceUuid, VmInstanceMetadataConstants.FILE_METADATA_SUFFIX); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.java` around lines 37 - 53, buildMetadataDir and buildVmMetadataPath duplicate the PrimaryStorageVO URL query and null-check; extract this into a shared helper (e.g., a private method getPrimaryStorageUrl or fetchPrimaryStorageUrl) that takes primaryStorageUuid, runs Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.url).eq(...).findValue(), throws the same CloudRuntimeException when null, and returns the url; then replace the repeated query blocks in buildMetadataDir and buildVmMetadataPath to call that helper and keep the existing usage of normalizeBaseDir and VmInstanceMetadataConstants unchanged.
🤖 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/VmExpungeMetadataFlow.java`:
- Around line 55-61: The flow VmExpungeMetadataFlow must not re-query
VolumeVO.primaryStorageUuid using rootVolumeUuid (since VmExpungeRootVolumeFlow
may have already deleted/flushed that record); instead obtain primaryStorageUuid
from the cached expunge context/spec passed into the expunge chain (e.g. use the
already-populated VmInstanceSpec or the RootVolumeSpec stored on the flow
context) and use that value for metadata cleanup, or move the metadata cleanup
to run before VmExpungeRootVolumeFlow; update VmExpungeMetadataFlow to read
primaryStorageUuid from the existing spec/context (not via Q.New on VolumeVO)
and keep the trigger.next() behavior unchanged.
In `@header/src/main/java/org/zstack/header/vm/VmInstanceState.java`:
- Around line 33-34: The Registering enum constant in VmInstanceState currently
uses Registering(null) and lacks a transactions() definition, so calls to
VmInstanceState.nextState(VmInstanceStateEvent) (used by methods like
VmInstanceBase.changeVmStateInDb()) will throw CloudRuntimeException; update the
Registering constant to provide a proper transactions() implementation listing
allowed VmInstanceStateEvent -> target VmInstanceState transitions (mirror
semantics of similar offline states), ensuring all expected events are handled
and returning the corresponding next states to prevent runtime errors.
In
`@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.java`:
- Around line 122-133: The createResourceRef method in
LocalStorageVmMetadataExtension constructs a LocalStorageResourceRefVO and calls
dbf.persist(ref) without checking the composite key (resourceUuid +
primaryStorageUuid + hostUuid), which can trigger unique-constraint errors on
duplicate inserts; either add an existence check before persisting (e.g., query
for an existing LocalStorageResourceRefVO by resourceUuid + primaryStorageUuid +
hostUuid and only call dbf.persist if null) or, if the extension points
afterVolumePersist and afterSnapshotPersist are not used anywhere, remove those
unused methods to eliminate the insertion path; update/createResourceRef,
afterVolumePersist, and afterSnapshotPersist accordingly to reflect the chosen
approach.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java`:
- Around line 49-58: The code currently falls back to PrimaryStorageVO.url when
mountPath is null, which causes path replacement to use an NFS export URL rather
than a host mount directory; remove the fallback that reads PrimaryStorageVO.url
and instead treat a missing PrimaryStorageVO_.mountPath as "replacement
disabled": in the method that builds metadata paths (referencing
buildMetadataDir(), buildVmMetadataPath(), PrimaryStorageVO_.mountPath and the
PathReplacementResult returned for targetPsUuid), ensure you only use mountPath,
log a warning if mountPath is null (including targetPsUuid context), set
result.setMetadataToCurrentPathMap(Collections.emptyMap()) and return, and do
not attempt to construct any prefix from PrimaryStorageVO.url.
---
Duplicate comments:
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java`:
- Around line 1983-1992: The handler currently ignores any caller-selected host
and always picks connectedHosts.get(0); change it to use msg.getHostUuid() when
present (e.g., if msg.getHostUuid() != null && !msg.getHostUuid().isEmpty()) as
the preferred hostUuid, and only fall back to connectedHosts.get(0). Update the
host selection before calling getBackendByHostUuid(hostUuid) in
handle(GetVmInstanceMetadataFromPrimaryStorageMsg) (and apply the same fix to
the two other handlers mentioned around lines 2032-2042 and 2057-2066) so the
code uses the caller-provided hostUuid first and only uses the first connected
host when msg.getHostUuid() is missing.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java`:
- Around line 2157-2160: The reply handling assumes rsp.metadataEntries is
non-null and calls forEach, which can NPE if agent returned null; before
iterating and before calling r.setVmInstanceMetadata ensure a non-null list
(e.g., replace null with Collections.emptyList() or new ArrayList<>()), then
call entry.setHostUuid(hostUuid) on that safe list and pass it to
r.setVmInstanceMetadata(...) before completion.success(r); update the block
around ScanVmInstanceMetadataFromPrimaryStorageReply, rsp.metadataEntries,
setHostUuid, r.setVmInstanceMetadata, and completion.success accordingly.
- Around line 44-45: The new handlers in NfsPrimaryStorageKVMBackend reference
several metadata message/reply types that are not imported and will cause
compile errors—add imports for GetVmInstanceMetadataFromPrimaryStorageMsg,
GetVmInstanceMetadataFromPrimaryStorageReply,
ScanVmInstanceMetadataFromPrimaryStorageMsg,
ScanVmInstanceMetadataFromPrimaryStorageReply,
CleanupVmInstanceMetadataOnPrimaryStorageMsg, and
CleanupVmInstanceMetadataOnPrimaryStorageReply to the import block (alongside
the existing UpdateVmInstanceMetadataOnPrimaryStorage* imports) so the class
compiles; also guard the iteration over rsp.metadataEntries (the forEach call
around line ~2157) with a null check (e.g., check rsp.metadataEntries != null
before calling forEach) to avoid a possible NullPointerException.
---
Nitpick comments:
In
`@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.java`:
- Around line 37-53: buildMetadataDir and buildVmMetadataPath duplicate the
PrimaryStorageVO URL query and null-check; extract this into a shared helper
(e.g., a private method getPrimaryStorageUrl or fetchPrimaryStorageUrl) that
takes primaryStorageUuid, runs
Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.url).eq(...).findValue(),
throws the same CloudRuntimeException when null, and returns the url; then
replace the repeated query blocks in buildMetadataDir and buildVmMetadataPath to
call that helper and keep the existing usage of normalizeBaseDir and
VmInstanceMetadataConstants unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 9337fddc-67ec-4dcb-ab1d-c66fcd39d9df
⛔ Files ignored due to path filters (5)
conf/globalConfig/vm.xmlis excluded by!**/*.xmlconf/persistence.xmlis excluded by!**/*.xmlconf/serviceConfig/primaryStorage.xmlis excluded by!**/*.xmlconf/serviceConfig/vmInstance.xmlis excluded by!**/*.xmlconf/springConfigXml/VmInstanceManager.xmlis excluded by!**/*.xml
📒 Files selected for processing (148)
compute/src/main/java/org/zstack/compute/vm/CleanupVmInstanceMetadataOnPrimaryStorageGC.javacompute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.javacompute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.javacompute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.javacompute/src/main/java/org/zstack/compute/vm/VmSystemTags.javaconf/db/upgrade/V5.0.0__schema.sqlheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataReply.javaheader/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIDeleteVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIRevertVolumeFromSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIShrinkVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIUpdateVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIDeleteVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIRevertVmFromSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIUngroupVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIUpdateVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/tag/APICreateSystemTagMsg.javaheader/src/main/java/org/zstack/header/tag/APICreateSystemTagsMsg.javaheader/src/main/java/org/zstack/header/tag/APIDeleteTagMsg.javaheader/src/main/java/org/zstack/header/tag/APIUpdateSystemTagMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachIsoToVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachL3NetworkToVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachVmNicToVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeInstanceOfferingMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeVmNicNetworkMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeVmNicStateMsg.javaheader/src/main/java/org/zstack/header/vm/APIConvertTemplatedVmInstanceToVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIConvertVmInstanceToTemplatedVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APICreateVmNicMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmBootModeMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmConsolePasswordMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmHostnameMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmNicMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmStaticIpMsg.javaheader/src/main/java/org/zstack/header/vm/APIDestroyVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIDetachIsoFromVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIDetachL3NetworkFromVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIExpungeVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIMigrateVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIRecoverVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIReimageVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootModeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootOrderMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootVolumeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmClockTrackMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmConsolePasswordMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmHostnameMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmQxlMemoryMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmSoundTypeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmStaticIpMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmNicDriverMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmPriorityMsg.javaheader/src/main/java/org/zstack/header/vm/VmInstanceState.javaheader/src/main/java/org/zstack/header/vm/cdrom/APICreateVmCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/cdrom/APISetVmInstanceDefaultCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/MetadataImpact.javaheader/src/main/java/org/zstack/header/vm/metadata/ResourceMetadata.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataReply.javaheader/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataConstants.javaheader/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataDTO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataCategory.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO_.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataErrors.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathBuildExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.javaheader/src/main/java/org/zstack/header/vm/metadata/VolumeResourceMetadata.javaheader/src/main/java/org/zstack/header/volume/APIAttachDataVolumeToVmMsg.javaheader/src/main/java/org/zstack/header/volume/APIChangeVolumeStateMsg.javaheader/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/volume/APIDeleteDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIDetachDataVolumeFromVmMsg.javaheader/src/main/java/org/zstack/header/volume/APIExpungeDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIFlattenVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIRecoverDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APISyncVolumeSizeMsg.javaheader/src/main/java/org/zstack/header/volume/APIUndoSnapshotCreationMsg.javaheader/src/main/java/org/zstack/header/volume/APIUpdateVolumeMsg.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/APILocalStorageMigrateVolumeMsg.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageHypervisorBackend.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulator.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulatorConfig.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageBackend.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackendCommands.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.javaresourceconfig/src/main/java/org/zstack/resourceconfig/APIDeleteResourceConfigMsg.javaresourceconfig/src/main/java/org/zstack/resourceconfig/APIUpdateResourceConfigMsg.javasdk/src/main/java/SourceClassMap.javasdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataAction.javasdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataResult.javasdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageAction.javasdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageResult.javasdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataAction.javasdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.javasdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageAction.javasdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageResult.javasdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataAction.javasdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataResult.javasdk/src/main/java/org/zstack/sdk/VmMetadataScanEntry.javastorage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.javatestlib/src/main/java/org/zstack/testlib/ApiHelper.groovytestlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovytestlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy
✅ Files skipped from review due to trivial changes (90)
- header/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataReply.java
- header/src/main/java/org/zstack/header/tag/APICreateSystemTagsMsg.java
- header/src/main/java/org/zstack/header/vm/APIAttachIsoToVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeInstanceOfferingMsg.java
- header/src/main/java/org/zstack/header/vm/APICreateVmNicMsg.java
- header/src/main/java/org/zstack/header/vm/APIDetachIsoFromVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIDetachL3NetworkFromVmMsg.java
- header/src/main/java/org/zstack/header/vm/APIExpungeVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootOrderMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmHostnameMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmStaticIpMsg.java
- header/src/main/java/org/zstack/header/vm/APIUpdateVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIUpdateVmNicDriverMsg.java
- header/src/main/java/org/zstack/header/vm/cdrom/APICreateVmCdRomMsg.java
- header/src/main/java/org/zstack/header/vm/cdrom/APISetVmInstanceDefaultCdRomMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataReply.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataCategory.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.java
- header/src/main/java/org/zstack/header/vm/metadata/VolumeResourceMetadata.java
- header/src/main/java/org/zstack/header/volume/APIAttachDataVolumeToVmMsg.java
- header/src/main/java/org/zstack/header/volume/APIDetachDataVolumeFromVmMsg.java
- compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java
- conf/db/upgrade/V5.0.0__schema.sql
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIShrinkVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIRevertVmFromSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIUngroupVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIUpdateVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/tag/APICreateSystemTagMsg.java
- header/src/main/java/org/zstack/header/vm/APIAttachVmNicToVmMsg.java
- header/src/main/java/org/zstack/header/vm/APIConvertTemplatedVmInstanceToVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmBootModeMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmConsolePasswordMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.java
- header/src/main/java/org/zstack/header/vm/APIRecoverVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIReimageVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootModeMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmClockTrackMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmConsolePasswordMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmSoundTypeMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEvent.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEventDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEvent.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/ResourceMetadata.java
- header/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataConstants.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO_.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataErrors.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathBuildExtensionPoint.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.java
- header/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.java
- header/src/main/java/org/zstack/header/volume/APIFlattenVolumeMsg.java
- header/src/main/java/org/zstack/header/volume/APIUndoSnapshotCreationMsg.java
- header/src/main/java/org/zstack/header/volume/APISyncVolumeSizeMsg.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/APILocalStorageMigrateVolumeMsg.java
- header/src/main/java/org/zstack/header/volume/APIUpdateVolumeMsg.java
- sdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEventDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataDTO.java
- sdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataResult.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataMsg.java
- sdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataResult.java
- sdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageResult.java
- testlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovy
- sdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageResult.java
- sdk/src/main/java/org/zstack/sdk/VmMetadataScanEntry.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.java
🚧 Files skipped from review as they are similar to previous changes (39)
- header/src/main/java/org/zstack/header/vm/APIDeleteVmStaticIpMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmQxlMemoryMsg.java
- header/src/main/java/org/zstack/header/vm/APIUpdateVmPriorityMsg.java
- header/src/main/java/org/zstack/header/volume/APIChangeVolumeStateMsg.java
- compute/src/main/java/org/zstack/compute/vm/CleanupVmInstanceMetadataOnPrimaryStorageGC.java
- compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIDeleteVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIRevertVolumeFromSnapshotMsg.java
- header/src/main/java/org/zstack/header/tag/APIDeleteTagMsg.java
- header/src/main/java/org/zstack/header/tag/APIUpdateSystemTagMsg.java
- header/src/main/java/org/zstack/header/vm/APIAttachL3NetworkToVmMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeVmNicNetworkMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeVmNicStateMsg.java
- header/src/main/java/org/zstack/header/vm/APIConvertVmInstanceToTemplatedVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIDestroyVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootVolumeMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEventDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/MetadataImpact.java
- header/src/main/java/org/zstack/header/volume/APIExpungeDataVolumeMsg.java
- header/src/main/java/org/zstack/header/volume/APIDeleteDataVolumeMsg.java
- header/src/main/java/org/zstack/header/volume/APIRecoverDataVolumeMsg.java
- resourceconfig/src/main/java/org/zstack/resourceconfig/APIUpdateResourceConfigMsg.java
- resourceconfig/src/main/java/org/zstack/resourceconfig/APIDeleteResourceConfigMsg.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageHypervisorBackend.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulatorConfig.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulator.java
- plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageBackend.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.java
- sdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataAction.java
- plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackendCommands.java
- sdk/src/main/java/SourceClassMap.java
- sdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageAction.java
- testlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy
- sdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageAction.java
| Crashed(VmInstanceStateEvent.crashed), | ||
| Registering(null); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 检查 fromVmInstanceState 返回值的使用方式,确认是否有 null 安全处理
rg -n "fromVmInstanceState\(" --type=java -A 5 -B 2
# 检查 Registering 状态的 VM 是否会进入 KVM 状态同步流程
rg -n "syncVmState|handleVmStateReport|VmStateChangedOnHostMsg" --type=java -C 3 | head -80Repository: MatheMatrix/zstack
Length of output: 9165
🏁 Script executed:
# 查看 KVMConstant.fromVmInstanceState() 的完整实现
sed -n '196,230p' plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.javaRepository: MatheMatrix/zstack
Length of output: 1164
🏁 Script executed:
# 查找 fromVmInstanceState 的所有调用处及其返回值使用方式
rg -n "fromVmInstanceState" --type=java -B 2 -A 8Repository: MatheMatrix/zstack
Length of output: 1184
🏁 Script executed:
# 查找 fromVmInstanceState 的所有调用处
rg "\.fromVmInstanceState\(" --type=java -B 3 -A 8Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 用更宽松的搜索方式,查找 fromVmInstanceState 的所有引用
rg "fromVmInstanceState" --type=java -B 2 -A 5Repository: MatheMatrix/zstack
Length of output: 845
🏁 Script executed:
# 检查是否有调用 fromVmInstanceState 的代码(尝试不同的搜索模式)
grep -r "fromVmInstanceState" --include="*.java" . 2>/dev/null | grep -v "public static KvmVmState fromVmInstanceState"Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查看 Registering 状态在代码中的实际应用场景
rg "Registering" --type=java -B 2 -A 2Repository: MatheMatrix/zstack
Length of output: 1035
🏁 Script executed:
# 搜索 offlineStates 的所有使用处
rg "offlineStates" --type=java -B 2 -A 3Repository: MatheMatrix/zstack
Length of output: 2445
🏁 Script executed:
# 验证 Registering 状态是否会实际被 VM 使用
rg "VmInstanceState\.Registering|state.*Registering" --type=java -B 2 -A 2Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查看 VmInstanceState.java 完整文件,检查 Registering 的 transactions 配置
cat -n header/src/main/java/org/zstack/header/vm/VmInstanceState.java | head -100Repository: MatheMatrix/zstack
Length of output: 6027
🏁 Script executed:
# 搜索是否有任何代码会将 VM 状态设置为 Registering
rg "Registering|nextState|transaction" --type=java header/src/main/java/org/zstack/header/vm/VmInstanceState.java -B 1 -A 1Repository: MatheMatrix/zstack
Length of output: 3378
🏁 Script executed:
# 查看 VmInstanceState.java 150-180 行,看是否 Registering 有 transactions
sed -n '150,200p' header/src/main/java/org/zstack/header/vm/VmInstanceState.javaRepository: MatheMatrix/zstack
Length of output: 3792
🏁 Script executed:
# 搜索是否有任何代码会使用 VmInstanceStateEvent.* 来触发状态转换到 Registering
rg "VmInstanceStateEvent\." --type=java | grep -i registRepository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 检查是否有代码会调用 state.nextState()
rg "\.nextState\(" --type=java -B 2 -A 2 | head -50Repository: MatheMatrix/zstack
Length of output: 5094
🏁 Script executed:
# 查看 VmInstanceState.java 中是否 Registering 之后还有 transactions 定义
tail -50 header/src/main/java/org/zstack/header/vm/VmInstanceState.javaRepository: MatheMatrix/zstack
Length of output: 2075
🏁 Script executed:
# 查看 VmInstanceStateEvent 中是否有与 Registering 相关的事件
rg "VmInstanceStateEvent" --type=java -A 2 | grep -i "regist"Repository: MatheMatrix/zstack
Length of output: 147
Registering 状态缺少事务定义,将导致状态转换异常。
Registering 状态定义为 Registering(null) 且已添加到 offlineStates 集合,但缺少必需的 transactions() 定义。如果任何代码路径调用 VmInstanceState.nextState(VmInstanceStateEvent) 尝试从 Registering 状态转换,将直接抛出 CloudRuntimeException:
throw new CloudRuntimeException(String.format("cannot find next state for current state[%s] on transaction event[%s]", this, event));
VmInstanceBase.changeVmStateInDb() 等多处代码会调用此方法。需要为 Registering 状态补充完整的事务定义,明确其允许的状态转换路径。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@header/src/main/java/org/zstack/header/vm/VmInstanceState.java` around lines
33 - 34, The Registering enum constant in VmInstanceState currently uses
Registering(null) and lacks a transactions() definition, so calls to
VmInstanceState.nextState(VmInstanceStateEvent) (used by methods like
VmInstanceBase.changeVmStateInDb()) will throw CloudRuntimeException; update the
Registering constant to provide a proper transactions() implementation listing
allowed VmInstanceStateEvent -> target VmInstanceState transitions (mirror
semantics of similar offline states), ensuring all expected events are handled
and returning the corresponding next states to prevent runtime errors.
| private void createResourceRef(String primaryStorageUuid, String resourceUuid, | ||
| String resourceType, String hostUuid, long size, Timestamp now) { | ||
| LocalStorageResourceRefVO ref = new LocalStorageResourceRefVO(); | ||
| ref.setPrimaryStorageUuid(primaryStorageUuid); | ||
| ref.setResourceUuid(resourceUuid); | ||
| ref.setResourceType(resourceType); | ||
| ref.setHostUuid(hostUuid); | ||
| ref.setSize(size); | ||
| ref.setCreateDate(now); | ||
| ref.setLastOpDate(now); | ||
| dbf.persist(ref); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 检查 LocalStorageResourceRefVO 的主键/唯一约束定义
ast-grep --pattern 'class LocalStorageResourceRefVO {
$$$
}'
# 查找 afterVolumePersist 和 afterSnapshotPersist 的调用点
rg -n "afterVolumePersist|afterSnapshotPersist" --type java -A 3Repository: MatheMatrix/zstack
Length of output: 2343
🏁 Script executed:
# 查找 LocalStorageResourceRefVO 类定义
fd -t f "LocalStorageResourceRefVO.java"Repository: MatheMatrix/zstack
Length of output: 279
🏁 Script executed:
# 搜索 LocalStorageResourceRefVO 的定义和约束
rg "class LocalStorageResourceRefVO" -A 30 --type javaRepository: MatheMatrix/zstack
Length of output: 5546
🏁 Script executed:
# 查找谁调用 afterVolumePersist 和 afterSnapshotPersist
rg "afterVolumePersist|afterSnapshotPersist" -B 5 --type java | head -100Repository: MatheMatrix/zstack
Length of output: 2985
🏁 Script executed:
# 检查是否有存在性检查的示例(查找 findByUuid)
rg "findByUuid.*resourceUuid" --type java -A 3Repository: MatheMatrix/zstack
Length of output: 1085
🏁 Script executed:
# 查找谁调用了 VmMetadataResourcePersistExtensionPoint 扩展点
rg "VmMetadataResourcePersistExtensionPoint" --type java -B 3 -A 3Repository: MatheMatrix/zstack
Length of output: 3219
🏁 Script executed:
# 查找 afterVolumePersist/afterSnapshotPersist 的实际调用位置
rg "\.afterVolumePersist|\.afterSnapshotPersist" --type java -B 5 -A 3Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查看 LocalStorageVmMetadataExtension 的完整实现
cat -n plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.javaRepository: MatheMatrix/zstack
Length of output: 7021
🏁 Script executed:
# 搜索扩展点的调用者 - 查找关键字 "afterVolumePersist" 的实际方法调用(带点号)
rg "afterVolumePersist\(" --type java -B 10 | head -80Repository: MatheMatrix/zstack
Length of output: 2402
🏁 Script executed:
# 查找 VmMetadataResourcePersistExtensionPoint 的使用者
rg "getPluginManager|loadPluginExtensionPoints|findExtensionPoint" --type java | grep -i metadataRepository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 在整个代码库中搜索对扩展点的引用和调用
rg "VmMetadataResourcePersistExtensionPoint" -B 2 -A 10 --type javaRepository: MatheMatrix/zstack
Length of output: 4949
🏁 Script executed:
# 搜索扩展点的实例化或调用
rg "getPluginManager|pluginManager" --type java | grep -i "VmMetadata\|afterVolume\|afterSnapshot" | head -20Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查找谁会调用 afterVolumePersist 或 afterSnapshotPersist - 查找可能的插件管理代码
fd -t f "*.java" | xargs grep -l "VmMetadataResourcePersistExtensionPoint" | head -10Repository: MatheMatrix/zstack
Length of output: 347
🏁 Script executed:
# 更直接的搜索 - 找到调用扩展点的代码
rg "for.*VmMetadataResourcePersistExtensionPoint|stream.*VmMetadataResourcePersistExtensionPoint" --type java -A 5Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查找调用 afterVolumePersist 的具体位置
rg "pluginMgr|plugin.*manager|.*afterVolume" --type java -B 5 -A 5 | head -100Repository: MatheMatrix/zstack
Length of output: 12061
🏁 Script executed:
# 查找谁调用了扩展点 - 搜索 VmMetadataResourcePersistExtensionPoint 的使用
rg "\.afterVolumePersist\(|\.afterSnapshotPersist\(" --type java -B 10 -A 3Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查找插件注册表相关的调用
rg "getExtensionList.*VmMetadata|VmMetadataResourcePersistExtensionPoint" --type java -B 5 -A 10Repository: MatheMatrix/zstack
Length of output: 5678
🏁 Script executed:
# 查找在哪里触发这些扩展点的调用
fd -t f LocalStorageVmMetadataExtension.java -o -name "*.java" | xargs grep -l "afterVolumePersist\|afterSnapshotPersist"Repository: MatheMatrix/zstack
Length of output: 294
🏁 Script executed:
# 搜索扩展点的实际调用 - 在整个仓库中搜索调用者
rg "for.*afterVolumePersist|stream.*afterVolumePersist|getExtensionList" --type java -A 5 | head -80Repository: MatheMatrix/zstack
Length of output: 8970
🏁 Script executed:
# 直接搜索包含 "afterVolumePersist" 或 "afterSnapshotPersist" 字符串的Java文件
rg "afterVolumePersist\|afterSnapshotPersist" --type java -lRepository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查看调用扩展点的可能位置 - 搜索 getExtensionList 和 VmMetadata
rg "getExtensionList.*Metadata\|Metadata.*getExtensionList" --type java -B 5 -A 10Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查找 VmMetadataResourcePersistExtensionPoint 的所有使用位置
rg "VmMetadataResourcePersistExtensionPoint" --type java -B 10 -A 10Repository: MatheMatrix/zstack
Length of output: 6456
🏁 Script executed:
# 查找所有文件中对 getExtensionList 的调用,然后过滤与 VmMetadata 相关的
rg "pluginRgty|pluginRegistry|extensionRegistry" --type java -A 5 | grep -B 5 -A 5 "afterVolume\|Metadata" | head -100Repository: MatheMatrix/zstack
Length of output: 9212
🏁 Script executed:
# 查找谁会加载和使用这个扩展点 - 搜索可能的使用模式
rg "getExtensionList.*getPrimaryStorageType\|getPrimaryStorageType.*getExtensionList" --type java -B 10 -A 10Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 或者直接查找包含 "VmMetadata" 的所有Java文件
fd --type f --name "*.java" -path "*/java/*" | xargs grep -l "VmMetadata" | head -20Repository: MatheMatrix/zstack
Length of output: 312
🏁 Script executed:
# 查找 VmInstanceResourceMetadataManager 类
fd VmInstanceResourceMetadataManagerRepository: MatheMatrix/zstack
Length of output: 245
🏁 Script executed:
# 在整个代码库中查找对 VmInstanceResourceMetadataManager 的使用,看它是否调用扩展点
rg "VmInstanceResourceMetadataManager" --type java -B 3 -A 10 | head -150Repository: MatheMatrix/zstack
Length of output: 16521
🏁 Script executed:
# 直接查找包含 "VmMetadata" 相关的所有 Java 文件
find . -type f -name "*.java" | xargs grep -l "VmMetadataResourcePersistExtensionPoint\|afterVolumePersist\|afterSnapshotPersist" 2>/dev/nullRepository: MatheMatrix/zstack
Length of output: 267
🏁 Script executed:
# 查看 VmInstanceResourceMetadataManagerImpl 的完整内容
cat compute/src/main/java/org/zstack/compute/vm/devices/VmInstanceResourceMetadataManagerImpl.javaRepository: MatheMatrix/zstack
Length of output: 17349
🏁 Script executed:
# 同时查看 VmInstanceResourceMetadataManager 接口
cat header/src/main/java/org/zstack/header/vm/devices/VmInstanceResourceMetadataManager.javaRepository: MatheMatrix/zstack
Length of output: 7292
🏁 Script executed:
# 在 VolumeBase 和 VolumeSnapshotTreeBase 中查找对扩展点的调用
rg "vidm\." storage/src/main/java/org/zstack/storage/volume/VolumeBase.java -B 3 -A 3 | head -100Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查找 afterVolumePersist 或 afterSnapshotPersist 在哪里被真正调用
rg "afterVolumePersist\(|afterSnapshotPersist\(" --type java -B 15 -A 5Repository: MatheMatrix/zstack
Length of output: 5569
🏁 Script executed:
# 查找 VmMetadataResourcePersistExtensionPoint 的使用 - 在扩展点列表中
rg "VmMetadataResourcePersistExtensionPoint\|getExtensionFromMap.*Metadata\|getExtensionList.*Metadata" --type java -B 10 -A 10Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 在整个仓库中搜索调用这些方法的地方
rg "\.afterVolumePersist\(|\.afterSnapshotPersist\(" --type javaRepository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查找包含 "VmMetadataResourcePersistExtensionPoint" 的所有引用
rg "VmMetadataResourcePersistExtensionPoint" --type javaRepository: MatheMatrix/zstack
Length of output: 593
🏁 Script executed:
# 搜索可能使用扩展点注册的插件管理器调用
rg "pluginRgty|pluginRegistry" storage/src/main/java/org/zstack/storage/volume/ --type java | grep -i "getExtension\|afterVolume\|afterSnapshot"Repository: MatheMatrix/zstack
Length of output: 6167
🏁 Script executed:
# 查找 VmMetadataResourcePersistExtensionPoint 是否被任何地方加载或使用
rg "getExtensionList\|getExtensionFromMap" --type java -A 2 | grep -B 2 "Metadata\|ResourcePersist"Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
# 查找任何与 VmMetadata 相关的动态调用或反射调用
rg "VmMetadata" --type java | grep -v "import\|interface\|extend\|implement"Repository: MatheMatrix/zstack
Length of output: 12633
🏁 Script executed:
# 检查是否有尚未执行的计划:查找与此扩展点相关的注释或 TODO
rg "afterVolume|afterSnapshot|createResourceRef" --type java -B 2 -A 2Repository: MatheMatrix/zstack
Length of output: 14207
🏁 Script executed:
# 最后验证:确认没有代码调用这些扩展点方法
rg "afterVolumePersist\(|afterSnapshotPersist\(" --type java -A 1 | grep -v "^--$" | grep -v "public void"Repository: MatheMatrix/zstack
Length of output: 1199
🏁 Script executed:
# 查看 LocalStorageBase 中的类似方法,比较实现
cat -n plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.java | sed -n '1690,1720p'Repository: MatheMatrix/zstack
Length of output: 1596
🏁 Script executed:
# 查看 LocalStorageBase 中的 createResourceRefVO 方法
rg -A 15 "private void createResourceRefVO" plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.javaRepository: MatheMatrix/zstack
Length of output: 750
🏁 Script executed:
# 最终确认:检查是否存在对这些扩展点的任何调用或引用
rg "pluginRgty.*VmMetadataResourcePersistExtensionPoint\|getExtensionList.*ResourcePersist\|getExtensionFromMap.*ResourcePersist" --type javaRepository: MatheMatrix/zstack
Length of output: 44
确认代码设计缺陷:需要添加幂等性保护或移除未使用的扩展点方法。
LocalStorageResourceRefVO 定义了复合主键(resourceUuid + primaryStorageUuid + hostUuid),createResourceRef 直接调用 dbf.persist() 而未进行存在性检查。若同一 (primaryStorageUuid, resourceUuid, hostUuid) 组合被重复插入,将触发数据库唯一约束异常。
但需要注意,afterVolumePersist 和 afterSnapshotPersist 这两个扩展点方法在整个代码库中未被任何地方调用(仅在接口定义和该类实现中存在),属于未使用的代码。应通过以下方式之一处理:
- 若计划未来使用,添加存在性检查:
if (dbf.findByUuid(resourceUuid, primaryStorageUuid, hostUuid) == null) { dbf.persist(ref); } - 若不再需要,删除这两个未使用的扩展点方法
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.java`
around lines 122 - 133, The createResourceRef method in
LocalStorageVmMetadataExtension constructs a LocalStorageResourceRefVO and calls
dbf.persist(ref) without checking the composite key (resourceUuid +
primaryStorageUuid + hostUuid), which can trigger unique-constraint errors on
duplicate inserts; either add an existence check before persisting (e.g., query
for an existing LocalStorageResourceRefVO by resourceUuid + primaryStorageUuid +
hostUuid and only call dbf.persist if null) or, if the extension points
afterVolumePersist and afterSnapshotPersist are not used anywhere, remove those
unused methods to eliminate the insertion path; update/createResourceRef,
afterVolumePersist, and afterSnapshotPersist accordingly to reflect the chosen
approach.
| String baseDir = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.mountPath).eq(PrimaryStorageVO_.uuid, targetPsUuid).findValue(); | ||
| if (baseDir == null) { | ||
| baseDir = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.url).eq(PrimaryStorageVO_.uuid, targetPsUuid).findValue(); | ||
| } | ||
| if (baseDir == null) { | ||
| logger.warn(String.format("NFS PS[uuid:%s] has no mountPath or url, path replacement disabled", targetPsUuid)); | ||
| PathReplacementResult result = new PathReplacementResult(); | ||
| result.setMetadataToCurrentPathMap(Collections.emptyMap()); | ||
| return result; | ||
| } |
There was a problem hiding this comment.
不要把 PrimaryStorageVO.url 当成 path replacement 的前缀。
这里替换的是宿主机侧文件路径,前面的 buildMetadataDir() / buildVmMetadataPath() 也都只认 mountPath。mountPath 缺失时回退到 url,会把 newPrefix 变成 NFS 导出地址而不是本地挂载目录,后续 KVM rebase 会把 backing file 改成无效路径。这里更安全的行为是直接禁用 replacement(或报错),不要继续用 url 生成前缀。
💡 建议修改
- String baseDir = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.mountPath).eq(PrimaryStorageVO_.uuid, targetPsUuid).findValue();
- if (baseDir == null) {
- baseDir = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.url).eq(PrimaryStorageVO_.uuid, targetPsUuid).findValue();
- }
- if (baseDir == null) {
- logger.warn(String.format("NFS PS[uuid:%s] has no mountPath or url, path replacement disabled", targetPsUuid));
+ String baseDir = Q.New(PrimaryStorageVO.class)
+ .select(PrimaryStorageVO_.mountPath)
+ .eq(PrimaryStorageVO_.uuid, targetPsUuid)
+ .findValue();
+ if (baseDir == null) {
+ logger.warn(String.format("NFS PS[uuid:%s] has no mountPath, path replacement disabled", targetPsUuid));
PathReplacementResult result = new PathReplacementResult();
result.setMetadataToCurrentPathMap(Collections.emptyMap());
return result;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| String baseDir = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.mountPath).eq(PrimaryStorageVO_.uuid, targetPsUuid).findValue(); | |
| if (baseDir == null) { | |
| baseDir = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.url).eq(PrimaryStorageVO_.uuid, targetPsUuid).findValue(); | |
| } | |
| if (baseDir == null) { | |
| logger.warn(String.format("NFS PS[uuid:%s] has no mountPath or url, path replacement disabled", targetPsUuid)); | |
| PathReplacementResult result = new PathReplacementResult(); | |
| result.setMetadataToCurrentPathMap(Collections.emptyMap()); | |
| return result; | |
| } | |
| String baseDir = Q.New(PrimaryStorageVO.class) | |
| .select(PrimaryStorageVO_.mountPath) | |
| .eq(PrimaryStorageVO_.uuid, targetPsUuid) | |
| .findValue(); | |
| if (baseDir == null) { | |
| logger.warn(String.format("NFS PS[uuid:%s] has no mountPath, path replacement disabled", targetPsUuid)); | |
| PathReplacementResult result = new PathReplacementResult(); | |
| result.setMetadataToCurrentPathMap(Collections.emptyMap()); | |
| return result; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java`
around lines 49 - 58, The code currently falls back to PrimaryStorageVO.url when
mountPath is null, which causes path replacement to use an NFS export URL rather
than a host mount directory; remove the fallback that reads PrimaryStorageVO.url
and instead treat a missing PrimaryStorageVO_.mountPath as "replacement
disabled": in the method that builds metadata paths (referencing
buildMetadataDir(), buildVmMetadataPath(), PrimaryStorageVO_.mountPath and the
PathReplacementResult returned for targetPsUuid), ensure you only use mountPath,
log a warning if mountPath is null (including targetPsUuid context), set
result.setMetadataToCurrentPathMap(Collections.emptyMap()) and return, and do
not attempt to construct any prefix from PrimaryStorageVO.url.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (5)
storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java (1)
1884-1888:⚠️ Potential issue | 🟡 Minor空扫描结果这里需要按空列表兜底。
re.getVmInstanceMetadata()只要有一个后端在“没有元数据”场景返回null,这里的stream()就会把正常空结果放大成 API 异常。💡 建议修正
- List<VmMetadataScanEntry> filtered = re.getVmInstanceMetadata().stream() + List<VmMetadataScanEntry> filtered = Optional.ofNullable(re.getVmInstanceMetadata()) + .orElse(Collections.emptyList()) + .stream() .filter(e -> !VmMetadataCategory.TEMPLATE_CACHE.toString().equals(e.getVmCategory())) .collect(Collectors.toList());🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java` around lines 1884 - 1888, re.getVmInstanceMetadata() can be null and calling stream() will throw; change the code that builds filtered metadata to defensively handle null by treating it as an empty list (e.g. use Optional.ofNullable(re.getVmInstanceMetadata()).orElse(Collections.emptyList()) or an if-null -> Collections.emptyList()) before streaming and filtering; ensure you still apply the existing filter on VmMetadataScanEntry.getVmCategory() and then call reply.setVmInstanceMetadata(filtered) so reply gets an empty list instead of triggering an exception (refer to variables/methods: re, getVmInstanceMetadata, VmMetadataScanEntry, VmMetadataCategory.TEMPLATE_CACHE, reply.setVmInstanceMetadata).compute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.java (1)
55-61:⚠️ Potential issue | 🟠 Major不要在 expunge 链路里重新查询 root volume 的主存 UUID。
这里依赖运行时再查
VolumeVO.primaryStorageUuid。一旦前序 expunge 步骤已经删除或 flush 掉 root volume 记录,psUuid就会变成null,这里直接跳过 cleanup,而且连 GC 都不会提交,VM metadata 会遗留在主存上。这里应改为从 expunge 前已缓存的 spec/context 读取primaryStorageUuid。🤖 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/VmExpungeMetadataFlow.java` around lines 55 - 61, The flow VmExpungeMetadataFlow must not re-query VolumeVO.primaryStorageUuid at runtime (psUuid) because prior expunge steps may have removed or flushed the VolumeVO; instead read the root volume primaryStorageUuid from the already-populated expunge spec/context (use the flow's spec/context object that contains rootVolumeUuid/primaryStorageUuid) and use that value for metadata cleanup; remove the Q.New(VolumeVO.class)... query, guard against null in the cached spec value, and proceed to trigger.next() only after using the cached primaryStorageUuid so GC/cleanup is correctly submitted.plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java (1)
1983-2004:⚠️ Potential issue | 🟠 Major不要忽略上游已经指定的
hostUuid。这三个 handler 都把目标主机强制改成了第一个 connected host。上游一旦已经在消息里选定目标 host,这里就会把请求发到另一个 backend/agent;同一个 NFS 同时挂到多个 hypervisor 集群时,metadata 读取/清理和 backing file rebase 都可能落到错误主机上。
💡 建议修正
- List<HostInventory> connectedHosts = factory.getConnectedHostForOperation(getSelfInventory()); - if (connectedHosts.isEmpty()) { - reply.setError(operr("no connected host found for NFS primary storage[uuid:%s]", self.getUuid())); - bus.reply(msg, reply); - return; - } - String hostUuid = connectedHosts.get(0).getUuid(); + String hostUuid = msg.getHostUuid(); + if (hostUuid == null || hostUuid.isEmpty()) { + List<HostInventory> connectedHosts = factory.getConnectedHostForOperation(getSelfInventory()); + if (connectedHosts.isEmpty()) { + reply.setError(operr("no connected host found for NFS primary storage[uuid:%s]", self.getUuid())); + bus.reply(msg, reply); + return; + } + hostUuid = connectedHosts.get(0).getUuid(); + } final NfsPrimaryStorageBackend backend = getBackendByHostUuid(hostUuid);Also applies to: 2032-2054, 2057-2079
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java` around lines 1983 - 2004, The handlers (e.g., handle(GetVmInstanceMetadataFromPrimaryStorageMsg msg) in NfsPrimaryStorage) currently ignore any hostUuid provided by the incoming message and always pick connectedHosts.get(0); change the logic to first check msg.getHostUuid() (or the upstream-specified host field) and use that hostUuid if present and the host is connected, otherwise fall back to selecting factory.getConnectedHostForOperation(getSelfInventory()).get(0). Then call getBackendByHostUuid(hostUuid) and backend.handle(...) with that resolved hostUuid; apply the same fix to the other similar handlers referenced (around lines 2032-2054 and 2057-2079) so upstream-selected hosts are honored.plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java (1)
48-58:⚠️ Potential issue | 🟠 Major缺少
mountPath时不要回退到PrimaryStorageVO.url。同一个类里的
buildMetadataDir()和buildVmMetadataPath()都只认mountPath;这里只有 path replacement 回退到url,会把宿主机侧文件路径替换成 NFS 导出地址。后续 rebase 写出的就是无效路径。💡 建议修正
- if (baseDir == null) { - baseDir = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.url).eq(PrimaryStorageVO_.uuid, targetPsUuid).findValue(); - } - if (baseDir == null) { - logger.warn(String.format("NFS PS[uuid:%s] has no mountPath or url, path replacement disabled", targetPsUuid)); + if (baseDir == null) { + logger.warn(String.format("NFS PS[uuid:%s] has no mountPath, path replacement disabled", targetPsUuid)); PathReplacementResult result = new PathReplacementResult(); result.setMetadataToCurrentPathMap(Collections.emptyMap()); return result; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java` around lines 48 - 58, The calculatePathReplacements method currently falls back to PrimaryStorageVO.url when PrimaryStorageVO_.mountPath is null, causing host-side metadata paths to be replaced with NFS export URLs; remove the fallback query so baseDir is obtained only from PrimaryStorageVO_.mountPath (keep the existing null check that logs and returns an empty metadata map), ensuring behavior matches buildMetadataDir() and buildVmMetadataPath() which only recognize mountPath; update references in calculatePathReplacements to rely solely on mountPath and do not substitute URL values.plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java (1)
2157-2160:⚠️ Potential issue | 🟡 Minor为扫描结果增加空列表兜底。
Line 2158 直接对
rsp.metadataEntries调用forEach()。agent 在“无结果”场景下如果返回null,这里会把正常空扫描变成 NPE,并导致整次扫描失败。先归一化为空列表,再补hostUuid并写回 reply 会更稳妥。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java` around lines 2157 - 2160, Normalize rsp.metadataEntries to an empty list before iterating to avoid NPE: in NfsPrimaryStorageKVMBackend where you create ScanVmInstanceMetadataFromPrimaryStorageReply r and call rsp.metadataEntries.forEach(...), first replace null with an empty list (e.g., Collections.emptyList() or new ArrayList<>(0)), then set hostUuid on each entry and call r.setVmInstanceMetadata(...) and completion.success(r); reference rsp.metadataEntries, hostUuid, ScanVmInstanceMetadataFromPrimaryStorageReply, r, and completion.success in your change.
🧹 Nitpick comments (2)
header/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.java (1)
10-11: 建议:显式指定表名以提高可维护性
@Table注解未显式指定表名,将依赖默认命名规则。为确保与数据库 schema 脚本一致且便于维护,建议显式指定表名。♻️ 建议的修改
`@Entity` -@Table +@Table(name = "VmMetadataFingerprintVO") public class VmMetadataFingerprintVO {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@header/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.java` around lines 10 - 11, VmMetadataFingerprintVO 的 `@Table` 注解未指定表名,导致依赖默认命名规则;请在 VmMetadataFingerprintVO 类上把 `@Table` 改为显式指定表名(例如 `@Table`(name = "vm_metadata_fingerprint") 或与现有 schema 一致的表名),确保与数据库 schema 脚本匹配并便于维护,同时保留现有的 `@Entity` 注解和任何导入不变。testlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy (1)
525-539: 测试模拟器已添加,但缺少 VFS hooks。新增的元数据操作模拟器仅返回空响应。如果需要在测试中模拟实际的元数据文件读写行为(例如验证元数据内容、扫描结果),建议参考其他操作(如
CREATE_EMPTY_VOLUME_PATH、DELETE_PATH)添加对应的 VFS hooks。当前实现可以满足基本的 API 调用测试,但无法验证元数据文件的实际操作逻辑。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy` around lines 525 - 539, 新增了针对 NFS 元数据操作的模拟器(NfsPrimaryStorageKVMBackend.WRITE_VM_METADATA_PATH、GET_VM_INSTANCE_METADATA_PATH、SCAN_VM_METADATA_PATH、CLEANUP_VM_METADATA_PATH)但仅返回空响应,无法验证实际文件读写/扫描逻辑;在这些 simulator 回调中添加对应的 VFS hooks(参考已有的 CREATE_EMPTY_VOLUME_PATH、DELETE_PATH 的实现),在 WRITE 回调写入模拟元数据到 VFS、在 GET/SCAN 回调从 VFS 读取并返回内容/扫描结果、在 CLEANUP 回调删除 VFS 上的模拟元数据,以便测试可以断言元数据的实际变化和内容。
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@header/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.java`:
- Around line 13-16: The `@ForeignKey` on VmMetadataFingerprintVO.vmInstanceUuid
creates a DB-level ON DELETE CASCADE which doesn't work with VmInstanceEO's
soft-delete; remove or change the `@ForeignKey`(onDeleteAction =
ReferenceOption.CASCADE) on vmInstanceUuid in VmMetadataFingerprintVO so the DB
does not rely on physical cascade, and add explicit application-level cleanup to
remove VmMetadataFingerprintVO records when a VM is soft-deleted (invoke
deletion from the VM deletion flow/handler — e.g., inside the VM delete service
or the existing cleanup task such as CleanupVmInstanceMetadataOnPrimaryStorageGC
or a dedicated DeleteVmMetadata method) so fingerprints are deleted when
VmInstanceEO is marked deleted. Ensure the new cleanup targets
VmMetadataFingerprintVO by vmInstanceUuid.
In
`@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.java`:
- Around line 3907-3909: The code iterates rsp.metadataEntries and directly
calls entry.setHostUuid(hostUuid), which can NPE if the list contains nulls;
update the LocalStorageKvmBackend handling to filter out null elements before
mutating and passing to reply (e.g., skip null entries when iterating
rsp.metadataEntries and only add non-null entries to
reply.setVmInstanceMetadata), ensuring you still setHostUuid(hostUuid) only on
non-null entry objects.
---
Duplicate comments:
In `@compute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.java`:
- Around line 55-61: The flow VmExpungeMetadataFlow must not re-query
VolumeVO.primaryStorageUuid at runtime (psUuid) because prior expunge steps may
have removed or flushed the VolumeVO; instead read the root volume
primaryStorageUuid from the already-populated expunge spec/context (use the
flow's spec/context object that contains rootVolumeUuid/primaryStorageUuid) and
use that value for metadata cleanup; remove the Q.New(VolumeVO.class)... query,
guard against null in the cached spec value, and proceed to trigger.next() only
after using the cached primaryStorageUuid so GC/cleanup is correctly submitted.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java`:
- Around line 1983-2004: The handlers (e.g.,
handle(GetVmInstanceMetadataFromPrimaryStorageMsg msg) in NfsPrimaryStorage)
currently ignore any hostUuid provided by the incoming message and always pick
connectedHosts.get(0); change the logic to first check msg.getHostUuid() (or the
upstream-specified host field) and use that hostUuid if present and the host is
connected, otherwise fall back to selecting
factory.getConnectedHostForOperation(getSelfInventory()).get(0). Then call
getBackendByHostUuid(hostUuid) and backend.handle(...) with that resolved
hostUuid; apply the same fix to the other similar handlers referenced (around
lines 2032-2054 and 2057-2079) so upstream-selected hosts are honored.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java`:
- Around line 2157-2160: Normalize rsp.metadataEntries to an empty list before
iterating to avoid NPE: in NfsPrimaryStorageKVMBackend where you create
ScanVmInstanceMetadataFromPrimaryStorageReply r and call
rsp.metadataEntries.forEach(...), first replace null with an empty list (e.g.,
Collections.emptyList() or new ArrayList<>(0)), then set hostUuid on each entry
and call r.setVmInstanceMetadata(...) and completion.success(r); reference
rsp.metadataEntries, hostUuid, ScanVmInstanceMetadataFromPrimaryStorageReply, r,
and completion.success in your change.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java`:
- Around line 48-58: The calculatePathReplacements method currently falls back
to PrimaryStorageVO.url when PrimaryStorageVO_.mountPath is null, causing
host-side metadata paths to be replaced with NFS export URLs; remove the
fallback query so baseDir is obtained only from PrimaryStorageVO_.mountPath
(keep the existing null check that logs and returns an empty metadata map),
ensuring behavior matches buildMetadataDir() and buildVmMetadataPath() which
only recognize mountPath; update references in calculatePathReplacements to rely
solely on mountPath and do not substitute URL values.
In `@storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java`:
- Around line 1884-1888: re.getVmInstanceMetadata() can be null and calling
stream() will throw; change the code that builds filtered metadata to
defensively handle null by treating it as an empty list (e.g. use
Optional.ofNullable(re.getVmInstanceMetadata()).orElse(Collections.emptyList())
or an if-null -> Collections.emptyList()) before streaming and filtering; ensure
you still apply the existing filter on VmMetadataScanEntry.getVmCategory() and
then call reply.setVmInstanceMetadata(filtered) so reply gets an empty list
instead of triggering an exception (refer to variables/methods: re,
getVmInstanceMetadata, VmMetadataScanEntry, VmMetadataCategory.TEMPLATE_CACHE,
reply.setVmInstanceMetadata).
---
Nitpick comments:
In
`@header/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.java`:
- Around line 10-11: VmMetadataFingerprintVO 的 `@Table` 注解未指定表名,导致依赖默认命名规则;请在
VmMetadataFingerprintVO 类上把 `@Table` 改为显式指定表名(例如 `@Table`(name =
"vm_metadata_fingerprint") 或与现有 schema 一致的表名),确保与数据库 schema 脚本匹配并便于维护,同时保留现有的
`@Entity` 注解和任何导入不变。
In `@testlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy`:
- Around line 525-539: 新增了针对 NFS
元数据操作的模拟器(NfsPrimaryStorageKVMBackend.WRITE_VM_METADATA_PATH、GET_VM_INSTANCE_METADATA_PATH、SCAN_VM_METADATA_PATH、CLEANUP_VM_METADATA_PATH)但仅返回空响应,无法验证实际文件读写/扫描逻辑;在这些
simulator 回调中添加对应的 VFS hooks(参考已有的 CREATE_EMPTY_VOLUME_PATH、DELETE_PATH 的实现),在
WRITE 回调写入模拟元数据到 VFS、在 GET/SCAN 回调从 VFS 读取并返回内容/扫描结果、在 CLEANUP 回调删除 VFS
上的模拟元数据,以便测试可以断言元数据的实际变化和内容。
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7efdeabc-baaf-4b63-8246-7caccf2dfeb0
⛔ Files ignored due to path filters (5)
conf/globalConfig/vm.xmlis excluded by!**/*.xmlconf/persistence.xmlis excluded by!**/*.xmlconf/serviceConfig/primaryStorage.xmlis excluded by!**/*.xmlconf/serviceConfig/vmInstance.xmlis excluded by!**/*.xmlconf/springConfigXml/VmInstanceManager.xmlis excluded by!**/*.xml
📒 Files selected for processing (148)
compute/src/main/java/org/zstack/compute/vm/CleanupVmInstanceMetadataOnPrimaryStorageGC.javacompute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.javacompute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.javacompute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.javacompute/src/main/java/org/zstack/compute/vm/VmSystemTags.javaconf/db/upgrade/V5.0.0__schema.sqlheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataReply.javaheader/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIDeleteVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIRevertVolumeFromSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIShrinkVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIUpdateVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIDeleteVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIRevertVmFromSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIUngroupVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIUpdateVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/tag/APICreateSystemTagMsg.javaheader/src/main/java/org/zstack/header/tag/APICreateSystemTagsMsg.javaheader/src/main/java/org/zstack/header/tag/APIDeleteTagMsg.javaheader/src/main/java/org/zstack/header/tag/APIUpdateSystemTagMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachIsoToVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachL3NetworkToVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachVmNicToVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeInstanceOfferingMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeVmNicNetworkMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeVmNicStateMsg.javaheader/src/main/java/org/zstack/header/vm/APIConvertTemplatedVmInstanceToVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIConvertVmInstanceToTemplatedVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APICreateVmNicMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmBootModeMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmConsolePasswordMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmHostnameMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmNicMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmStaticIpMsg.javaheader/src/main/java/org/zstack/header/vm/APIDestroyVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIDetachIsoFromVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIDetachL3NetworkFromVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIExpungeVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIMigrateVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIRecoverVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIReimageVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootModeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootOrderMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootVolumeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmClockTrackMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmConsolePasswordMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmHostnameMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmQxlMemoryMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmSoundTypeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmStaticIpMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmNicDriverMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmPriorityMsg.javaheader/src/main/java/org/zstack/header/vm/VmInstanceState.javaheader/src/main/java/org/zstack/header/vm/cdrom/APICreateVmCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/cdrom/APISetVmInstanceDefaultCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/MetadataImpact.javaheader/src/main/java/org/zstack/header/vm/metadata/ResourceMetadata.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataReply.javaheader/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataConstants.javaheader/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataDTO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataCategory.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO_.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataErrors.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathBuildExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.javaheader/src/main/java/org/zstack/header/vm/metadata/VolumeResourceMetadata.javaheader/src/main/java/org/zstack/header/volume/APIAttachDataVolumeToVmMsg.javaheader/src/main/java/org/zstack/header/volume/APIChangeVolumeStateMsg.javaheader/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/volume/APIDeleteDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIDetachDataVolumeFromVmMsg.javaheader/src/main/java/org/zstack/header/volume/APIExpungeDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIFlattenVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIRecoverDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APISyncVolumeSizeMsg.javaheader/src/main/java/org/zstack/header/volume/APIUndoSnapshotCreationMsg.javaheader/src/main/java/org/zstack/header/volume/APIUpdateVolumeMsg.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/APILocalStorageMigrateVolumeMsg.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageHypervisorBackend.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulator.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulatorConfig.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageBackend.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackendCommands.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.javaresourceconfig/src/main/java/org/zstack/resourceconfig/APIDeleteResourceConfigMsg.javaresourceconfig/src/main/java/org/zstack/resourceconfig/APIUpdateResourceConfigMsg.javasdk/src/main/java/SourceClassMap.javasdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataAction.javasdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataResult.javasdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageAction.javasdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageResult.javasdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataAction.javasdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.javasdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageAction.javasdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageResult.javasdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataAction.javasdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataResult.javasdk/src/main/java/org/zstack/sdk/VmMetadataScanEntry.javastorage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.javatestlib/src/main/java/org/zstack/testlib/ApiHelper.groovytestlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovytestlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy
✅ Files skipped from review due to trivial changes (90)
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataReply.java
- sdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.java
- sdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataResult.java
- header/src/main/java/org/zstack/header/vm/APIMigrateVmMsg.java
- header/src/main/java/org/zstack/header/vm/APICreateVmNicMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataCategory.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/vm/APIAttachL3NetworkToVmMsg.java
- header/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.java
- header/src/main/java/org/zstack/header/vm/APIUpdateVmPriorityMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmSoundTypeMsg.java
- resourceconfig/src/main/java/org/zstack/resourceconfig/APIDeleteResourceConfigMsg.java
- header/src/main/java/org/zstack/header/volume/APISyncVolumeSizeMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsgDoc_zh_cn.groovy
- sdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataResult.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEventDoc_zh_cn.groovy
- sdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageResult.java
- header/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIShrinkVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/APISetVmConsolePasswordMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataReply.java
- header/src/main/java/org/zstack/header/vm/APIExpungeVmInstanceMsg.java
- header/src/main/java/org/zstack/header/tag/APICreateSystemTagMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIUngroupVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/tag/APIUpdateSystemTagMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmHostnameMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootOrderMsg.java
- header/src/main/java/org/zstack/header/vm/APIConvertTemplatedVmInstanceToVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIRecoverVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootVolumeMsg.java
- header/src/main/java/org/zstack/header/vm/APIReimageVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/cdrom/APICreateVmCdRomMsg.java
- header/src/main/java/org/zstack/header/vm/APIUpdateVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathBuildExtensionPoint.java
- header/src/main/java/org/zstack/header/volume/APIExpungeDataVolumeMsg.java
- header/src/main/java/org/zstack/header/volume/APIUpdateVolumeMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.java
- header/src/main/java/org/zstack/header/vm/metadata/VolumeResourceMetadata.java
- header/src/main/java/org/zstack/header/vm/metadata/ResourceMetadata.java
- header/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageMsg.java
- compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/volume/APIFlattenVolumeMsg.java
- header/src/main/java/org/zstack/header/vm/APIDestroyVmInstanceMsg.java
- testlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovy
- header/src/main/java/org/zstack/header/vm/APIChangeVmNicStateMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootModeMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmConsolePasswordMsg.java
- header/src/main/java/org/zstack/header/vm/APIAttachVmNicToVmMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmBootModeMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeInstanceOfferingMsg.java
- header/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIDeleteVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/APIDetachL3NetworkFromVmMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/APIUpdateVmNicDriverMsg.java
- header/src/main/java/org/zstack/header/vm/APIAttachIsoToVmInstanceMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIDeleteVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/APIDetachIsoFromVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEventDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataConstants.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEventDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsgDoc_zh_cn.groovy
- compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java
- conf/db/upgrade/V5.0.0__schema.sql
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.java
- sdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageResult.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO_.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmNicMsg.java
- sdk/src/main/java/org/zstack/sdk/VmMetadataScanEntry.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEvent.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIUpdateVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO.java
- header/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataDTO.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageMsg.java
🚧 Files skipped from review as they are similar to previous changes (34)
- header/src/main/java/org/zstack/header/vm/APISetVmQxlMemoryMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmStaticIpMsg.java
- header/src/main/java/org/zstack/header/tag/APIDeleteTagMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIUpdateVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/volume/APIDeleteDataVolumeMsg.java
- header/src/main/java/org/zstack/header/volume/APIAttachDataVolumeToVmMsg.java
- header/src/main/java/org/zstack/header/volume/APIRecoverDataVolumeMsg.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/APILocalStorageMigrateVolumeMsg.java
- compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java
- resourceconfig/src/main/java/org/zstack/resourceconfig/APIUpdateResourceConfigMsg.java
- header/src/main/java/org/zstack/header/volume/APIDetachDataVolumeFromVmMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmClockTrackMsg.java
- header/src/main/java/org/zstack/header/vm/cdrom/APISetVmInstanceDefaultCdRomMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/MetadataImpact.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulatorConfig.java
- header/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.java
- compute/src/main/java/org/zstack/compute/vm/CleanupVmInstanceMetadataOnPrimaryStorageGC.java
- header/src/main/java/org/zstack/header/volume/APIChangeVolumeStateMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeVmNicNetworkMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIRevertVmFromSnapshotGroupMsg.java
- sdk/src/main/java/SourceClassMap.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/APIConvertVmInstanceToTemplatedVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataErrors.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEvent.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsgDoc_zh_cn.groovy
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulator.java
- sdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataAction.java
- sdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataAction.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.java
| @Id | ||
| @Column | ||
| @ForeignKey(parentEntityClass = VmInstanceEO.class, onDeleteAction = ReferenceOption.CASCADE) | ||
| private String vmInstanceUuid; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 检查是否存在应用层清理 VmMetadataFingerprintVO 的逻辑
echo "=== 查找删除 VmMetadataFingerprintVO 的代码 ==="
rg -n "VmMetadataFingerprintVO" --type=java -C3
echo ""
echo "=== 查找 VM 删除扩展点中是否处理 metadata fingerprint ==="
rg -n "afterDeleteVm|beforeDeleteVm|VmInstanceDestroyExtensionPoint" --type=java -C2 | head -100Repository: MatheMatrix/zstack
Length of output: 4433
🏁 Script executed:
#!/bin/bash
# 1. Check VmInstanceEO soft-delete implementation
echo "=== VmInstanceEO 表结构(检查 deleted 列)==="
rg -n "class VmInstanceEO" --type=java -A 30 | head -50
echo ""
echo "=== 查找 VmMetadata 相关的删除逻辑 ==="
rg -n "delete.*[Vv]mMetadata|[Vv]mMetadata.*delete" --type=java -i
echo ""
echo "=== 查找 VM 销毁流程中的清理逻辑 ==="
rg -n "class VmInstanceBase" --type=java -A 5 | head -20
echo ""
echo "=== 查找 VmInstanceDestroyExtensionPoint 的实现类 ==="
rg -n "implements VmInstanceDestroyExtensionPoint" --type=javaRepository: MatheMatrix/zstack
Length of output: 1989
🏁 Script executed:
#!/bin/bash
# 查找 VmMetadataFingerprintVO 的迁移脚本和初始化
echo "=== 查找迁移脚本中的 VmMetadataFingerprintVO ==="
fd -e sql . conf/db | xargs rg "VmMetadataFingerprint|vm_metadata_fingerprint" 2>/dev/null | head -30
echo ""
echo "=== 查找数据库触发器或清理逻辑 ==="
fd -e sql . conf/db | xargs rg -i "trigger|procedure|cleanup|orphan|delete.*metadata" 2>/dev/null | grep -i "metadata\|fingerprint" | head -20
echo ""
echo "=== 检查 VmMetadataFingerprintVO 文件的完整内容 ==="
cat header/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.java
echo ""
echo "=== 查找相关的管理器/处理类 ==="
rg -n "VmMetadata" --type=java | grep -i "manager\|handler\|impl" | head -20Repository: MatheMatrix/zstack
Length of output: 3436
🏁 Script executed:
#!/bin/bash
# 查找定时清理或 GC 任务
echo "=== 查找 GC 或定时清理任务 ==="
rg -n "gc|GC|cleanup|scheduled|Scheduled|Cron|cron" --type=java | grep -i "metadata\|fingerprint" | head -20
echo ""
echo "=== 查找数据库清理脚本 ==="
fd -e sql . conf/db | xargs rg -i "delete.*from.*metadata|cleanup" | grep -i "metadata" | head -20
echo ""
echo "=== 查看完整的迁移脚本中关于 VmMetadataFingerprintVO 的定义 ==="
rg -A 20 "CREATE TABLE.*VmMetadataFingerprintVO" conf/db/upgrade/V5.0.0__schema.sql
echo ""
echo "=== 查找是否有其他软删除相关的 VO 及其处理方式 ==="
rg -n "ForeignKey.*CASCADE" --type=java | head -30Repository: MatheMatrix/zstack
Length of output: 10843
数据库级 CASCADE 约束对软删除无效,将导致孤儿记录
VmInstanceEO 使用软删除模式(包含 deleted 列),但 VmMetadataFingerprintVO 的 @ForeignKey 配置了 ON DELETE CASCADE 约束。
数据库层级的 CASCADE 仅在物理删除行时触发。由于软删除只更新 deleted 字段而不物理删除行,该约束永远不会被激活,导致 VmMetadataFingerprintVO 中的关联记录在 VM 被删除后仍然残留在数据库中。
检查结果显示:
- 没有找到应用层清理 VmMetadataFingerprintVO 数据库记录的机制
- 现有的清理逻辑(CleanupVmInstanceMetadataOnPrimaryStorageGC)仅处理主存储上的元数据,不涉及数据库记录
建议移除数据库层级的 CASCADE 约束,并在 VM 删除流程中显式删除关联的 fingerprint 记录。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@header/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.java`
around lines 13 - 16, The `@ForeignKey` on VmMetadataFingerprintVO.vmInstanceUuid
creates a DB-level ON DELETE CASCADE which doesn't work with VmInstanceEO's
soft-delete; remove or change the `@ForeignKey`(onDeleteAction =
ReferenceOption.CASCADE) on vmInstanceUuid in VmMetadataFingerprintVO so the DB
does not rely on physical cascade, and add explicit application-level cleanup to
remove VmMetadataFingerprintVO records when a VM is soft-deleted (invoke
deletion from the VM deletion flow/handler — e.g., inside the VM delete service
or the existing cleanup task such as CleanupVmInstanceMetadataOnPrimaryStorageGC
or a dedicated DeleteVmMetadata method) so fingerprints are deleted when
VmInstanceEO is marked deleted. Ensure the new cleanup targets
VmMetadataFingerprintVO by vmInstanceUuid.
| if (rsp.metadataEntries != null) { | ||
| rsp.metadataEntries.forEach(entry -> entry.setHostUuid(hostUuid)); | ||
| reply.setVmInstanceMetadata(rsp.metadataEntries); |
There was a problem hiding this comment.
补齐 metadataEntries 元素级空值防护。
Line 3908 直接对元素调用 setHostUuid;若 agent 返回列表中含 null 元素,仍会触发 NPE。建议在赋值前过滤空元素。
💡 建议修改
public void success(ScanVmMetadataRsp rsp) {
ScanVmInstanceMetadataFromPrimaryStorageReply reply = new ScanVmInstanceMetadataFromPrimaryStorageReply();
if (rsp.metadataEntries != null) {
- rsp.metadataEntries.forEach(entry -> entry.setHostUuid(hostUuid));
- reply.setVmInstanceMetadata(rsp.metadataEntries);
+ List<VmMetadataScanEntry> entries = rsp.metadataEntries.stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ entries.forEach(entry -> entry.setHostUuid(hostUuid));
+ reply.setVmInstanceMetadata(entries);
} else {
reply.setVmInstanceMetadata(Collections.emptyList());
}
completion.success(reply);
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.java`
around lines 3907 - 3909, The code iterates rsp.metadataEntries and directly
calls entry.setHostUuid(hostUuid), which can NPE if the list contains nulls;
update the LocalStorageKvmBackend handling to filter out null elements before
mutating and passing to reply (e.g., skip null entries when iterating
rsp.metadataEntries and only add non-null entries to
reply.setVmInstanceMetadata), ensuring you still setHostUuid(hostUuid) only on
non-null entry objects.
fd6171f to
15b0d24
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (4)
plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.java (1)
3907-3909:⚠️ Potential issue | 🟡 Minor补齐
metadataEntries的元素级空值保护。现在只兜底了列表本身为
null的情况;如果 agent 返回的数组里夹带null元素,Line 3908 这里仍然会 NPE。💡建议修改
- if (rsp.metadataEntries != null) { - rsp.metadataEntries.forEach(entry -> entry.setHostUuid(hostUuid)); - reply.setVmInstanceMetadata(rsp.metadataEntries); - } else { - reply.setVmInstanceMetadata(Collections.emptyList()); - } + List<VmMetadataScanEntry> entries = rsp.metadataEntries == null + ? Collections.emptyList() + : rsp.metadataEntries.stream() + .filter(Objects::nonNull) + .collect(Collectors.toList()); + entries.forEach(entry -> entry.setHostUuid(hostUuid)); + reply.setVmInstanceMetadata(entries);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.java` around lines 3907 - 3909, Protect against null elements in rsp.metadataEntries before calling entry.setHostUuid to avoid NPEs: when rsp.metadataEntries is non-null, filter out any null entries (e.g., using a stream or iterative check) and only call entry.setHostUuid(hostUuid) on non-null entries, then pass the filtered list to reply.setVmInstanceMetadata; ensure you end up setting an empty list (not null) if all elements are removed so reply.setVmInstanceMetadata always receives a safe list.plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java (1)
1983-2005:⚠️ Potential issue | 🟠 Major优先使用消息里的
hostUuid,不要无条件回退到第一个 connected host。这三个 handler 现在都会覆盖调用方已经选好的 host 路由。
compute/src/main/java/org/zstack/compute/vm/CleanupVmInstanceMetadataOnPrimaryStorageGC.java的 Line 46 已经把hostUuid写进CleanupVmInstanceMetadataOnPrimaryStorageMsg;这里再改成connectedHosts.get(0),同一个 NFS 同时挂到多个集群/不同 backend 时,可能把请求发到错误的 backend/agent。另两个 handler 也应保持同样的处理顺序:先尊重消息里的hostUuid,缺失时再 fallback。💡建议修改
- List<HostInventory> connectedHosts = factory.getConnectedHostForOperation(getSelfInventory()); - if (connectedHosts.isEmpty()) { - reply.setError(operr("no connected host found for NFS primary storage[uuid:%s]", self.getUuid())); - bus.reply(msg, reply); - return; - } - String hostUuid = connectedHosts.get(0).getUuid(); + String hostUuid = msg.getHostUuid(); + if (hostUuid == null || hostUuid.isEmpty()) { + List<HostInventory> connectedHosts = factory.getConnectedHostForOperation(getSelfInventory()); + if (connectedHosts.isEmpty()) { + reply.setError(operr("no connected host found for NFS primary storage[uuid:%s]", self.getUuid())); + bus.reply(msg, reply); + return; + } + hostUuid = connectedHosts.get(0).getUuid(); + } final NfsPrimaryStorageBackend backend = getBackendByHostUuid(hostUuid);Also applies to: 2032-2055, 2057-2079
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java` around lines 1983 - 2005, The handler handle(GetVmInstanceMetadataFromPrimaryStorageMsg msg) currently ignores a caller-provided hostUuid and always picks connectedHosts.get(0); change the host selection to first prefer the hostUuid from the message (e.g. msg.getHostUuid() when non-null/non-empty and a backend exists for it) and only fall back to using connectedHosts.get(0) when the message has no hostUuid or the specified host is not connected; apply the same change in the other two handlers that call getBackendByHostUuid/getConnectedHostForOperation so that backend selection uses the message-provided hostUuid first and only then chooses the first connected host.storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java (1)
1884-1888:⚠️ Potential issue | 🟡 Minor空扫描结果要先归一化成空列表。
Line 1885 直接对
re.getVmInstanceMetadata()调stream()。只要某个后端在“没有 metadata”场景返回null,一次正常的空扫描就会被放大成 API 异常。💡 建议修改
- List<VmMetadataScanEntry> filtered = re.getVmInstanceMetadata().stream() + List<VmMetadataScanEntry> filtered = Optional.ofNullable(re.getVmInstanceMetadata()) + .orElse(Collections.emptyList()) + .stream() .filter(e -> !VmMetadataCategory.TEMPLATE_CACHE.toString().equals(e.getVmCategory())) .collect(Collectors.toList());🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java` around lines 1884 - 1888, The code calls re.getVmInstanceMetadata().stream() which will NPE if getVmInstanceMetadata() returns null; update the logic in PrimaryStorageBase where ScanVmInstanceMetadataFromPrimaryStorageReply re is handled to normalize re.getVmInstanceMetadata() into an empty list when null (e.g., assign to a local list variable), then perform the filter on that list and pass the resulting filtered list to reply.setVmInstanceMetadata(filtered).compute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.java (1)
55-60:⚠️ Potential issue | 🔴 Critical不要在 expunge 链路里重新查询 root volume 的主存储。
结合
conf/springConfigXml/VmInstanceManager.xml的执行顺序,VmExpungeMetadataFlow是在VmExpungeRootVolumeFlow之后运行的。Line 55 再查VolumeVO.primaryStorageUuid依赖 root volume 记录仍然存在;一旦前序 flow 已经删除或 flush 了这条记录,这里就会直接跳过 cleanup,连 GC 都不会提交,最终把 VM metadata 留在主存储上。这里应改为从 expunge 前已缓存的 spec/context 读取primaryStorageUuid,或者把 metadata cleanup 前移。🤖 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/VmExpungeMetadataFlow.java` around lines 55 - 60, VmExpungeMetadataFlow must not re-query VolumeVO.primaryStorageUuid (currently done with Q.New(...) using rootVolumeUuid) because VmExpungeRootVolumeFlow may have already removed/flushed the volume record; instead obtain the primaryStorageUuid from the expunge context/spec that was prepared earlier (use the cached value placed by the prior flow or the VM/volume spec attached to the chain) or move the metadata cleanup into VmExpungeRootVolumeFlow before the volume record is deleted; update VmExpungeMetadataFlow to read primaryStorageUuid from the cached spec/context (not the DB) and then proceed to trigger.next().
🧹 Nitpick comments (5)
sdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataAction.java (1)
5-5: 冗余的导入语句。
import org.zstack.sdk.*;是冗余的,因为此类已经在org.zstack.sdk包中。♻️ 建议修复
-import org.zstack.sdk.*;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataAction.java` at line 5, 该类 UpdateVmInstanceMetadataAction 位于 org.zstack.sdk 包内,顶端的通配符导入语句 "import org.zstack.sdk.*;" 是冗余的;请删除该导入行(或替换为仅需的具体类型导入,如果类引用了其他包的类型),确保类头部不包含未使用的通配符导入以消除冗余。sdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataAction.java (1)
5-5: 冗余的导入语句。
import org.zstack.sdk.*;是冗余的,因为此类已经在org.zstack.sdk包中。♻️ 建议修复
-import org.zstack.sdk.*;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataAction.java` at line 5, The file contains a redundant import "import org.zstack.sdk.*;" in the CleanupVmInstanceMetadataAction class; remove that wildcard import since the class resides in the same package (org.zstack.sdk) and the import is unnecessary—open the CleanupVmInstanceMetadataAction.java file, delete the line with "import org.zstack.sdk.*;", keep any other specific imports if present, and ensure the file still compiles.sdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageAction.java (1)
5-5: 冗余的导入语句。
import org.zstack.sdk.*;是冗余的,因为此类已经在org.zstack.sdk包中。♻️ 建议修复
-import org.zstack.sdk.*;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageAction.java` at line 5, Remove the redundant wildcard import line "import org.zstack.sdk.*;" from the GetVmInstanceMetadataFromPrimaryStorageAction class; since the class is already in the org.zstack.sdk package, delete that import and verify the file still compiles (add any explicit imports only if the compiler reports missing symbols).compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java (1)
140-140: 建议为VM_METADATA_LAST_REFRESH_VERSION添加验证注解。其他 GlobalConfig 定义通常包含
@GlobalConfigValidation注解来约束有效值。如果此版本字段应为数字类型,建议添加验证(如@GlobalConfigValidation(numberGreaterThan = -1));如果允许任意字符串值,可以添加@GlobalConfigValidation无参注解以保持一致性。🤖 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/VmGlobalConfig.java` at line 140, The GlobalConfig VM_METADATA_LAST_REFRESH_VERSION lacks the usual `@GlobalConfigValidation` annotation; add `@GlobalConfigValidation` to the VM_METADATA_LAST_REFRESH_VERSION declaration and, if this value must be numeric, use a numeric constraint such as `@GlobalConfigValidation`(numberGreaterThan = -1) on the VM_METADATA_LAST_REFRESH_VERSION GlobalConfig to enforce valid values and match other GlobalConfig definitions.plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java (1)
87-99:extractOldPrefix()方法与LocalStorageVmMetadataExtension存在重复逻辑。此方法与
LocalStorageVmMetadataExtension.extractOldPrefix()完全相同,包括 markers 数组和提取逻辑。建议将此方法和 markers 常量抽取到共享工具类(如VmMetadataPathUtils)中,减少代码重复。♻️ 建议的重构方案
创建共享工具类:
// 新文件: storage/src/main/java/org/zstack/storage/primary/VmMetadataPathUtils.java public class VmMetadataPathUtils { private static final String[] PATH_MARKERS = {"/rootVolumes/", "/dataVolumes/", "/volumeSnapshots/", "/memory/"}; public static String extractOldPrefix(String path) { if (path == null || !path.startsWith("/")) { return null; } for (String marker : PATH_MARKERS) { int idx = path.indexOf(marker); if (idx >= 0) { return path.substring(0, idx + 1); } } return null; } }然后在
NfsVmMetadataExtension和LocalStorageVmMetadataExtension中调用:- private String extractOldPrefix(String path) { - if (path == null || !path.startsWith("/")) { - return null; - } - String[] markers = {"/rootVolumes/", "/dataVolumes/", "/volumeSnapshots/", "/memory/"}; - for (String marker : markers) { - int idx = path.indexOf(marker); - if (idx >= 0) { - return path.substring(0, idx + 1); - } - } - return null; - } + // 使用 VmMetadataPathUtils.extractOldPrefix(path)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java` around lines 87 - 99, The extractOldPrefix logic in NfsVmMetadataExtension duplicates LocalStorageVmMetadataExtension; create a shared utility (e.g., class VmMetadataPathUtils) that exposes a static PATH_MARKERS constant and a static extractOldPrefix(String) implementing the existing logic, then replace the private extractOldPrefix method in NfsVmMetadataExtension and the one in LocalStorageVmMetadataExtension to call VmMetadataPathUtils.extractOldPrefix(path) so both classes reuse the single implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@compute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.java`:
- Around line 55-60: VmExpungeMetadataFlow must not re-query
VolumeVO.primaryStorageUuid (currently done with Q.New(...) using
rootVolumeUuid) because VmExpungeRootVolumeFlow may have already removed/flushed
the volume record; instead obtain the primaryStorageUuid from the expunge
context/spec that was prepared earlier (use the cached value placed by the prior
flow or the VM/volume spec attached to the chain) or move the metadata cleanup
into VmExpungeRootVolumeFlow before the volume record is deleted; update
VmExpungeMetadataFlow to read primaryStorageUuid from the cached spec/context
(not the DB) and then proceed to trigger.next().
In
`@plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.java`:
- Around line 3907-3909: Protect against null elements in rsp.metadataEntries
before calling entry.setHostUuid to avoid NPEs: when rsp.metadataEntries is
non-null, filter out any null entries (e.g., using a stream or iterative check)
and only call entry.setHostUuid(hostUuid) on non-null entries, then pass the
filtered list to reply.setVmInstanceMetadata; ensure you end up setting an empty
list (not null) if all elements are removed so reply.setVmInstanceMetadata
always receives a safe list.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java`:
- Around line 1983-2005: The handler
handle(GetVmInstanceMetadataFromPrimaryStorageMsg msg) currently ignores a
caller-provided hostUuid and always picks connectedHosts.get(0); change the host
selection to first prefer the hostUuid from the message (e.g. msg.getHostUuid()
when non-null/non-empty and a backend exists for it) and only fall back to using
connectedHosts.get(0) when the message has no hostUuid or the specified host is
not connected; apply the same change in the other two handlers that call
getBackendByHostUuid/getConnectedHostForOperation so that backend selection uses
the message-provided hostUuid first and only then chooses the first connected
host.
In `@storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java`:
- Around line 1884-1888: The code calls re.getVmInstanceMetadata().stream()
which will NPE if getVmInstanceMetadata() returns null; update the logic in
PrimaryStorageBase where ScanVmInstanceMetadataFromPrimaryStorageReply re is
handled to normalize re.getVmInstanceMetadata() into an empty list when null
(e.g., assign to a local list variable), then perform the filter on that list
and pass the resulting filtered list to reply.setVmInstanceMetadata(filtered).
---
Nitpick comments:
In `@compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java`:
- Line 140: The GlobalConfig VM_METADATA_LAST_REFRESH_VERSION lacks the usual
`@GlobalConfigValidation` annotation; add `@GlobalConfigValidation` to the
VM_METADATA_LAST_REFRESH_VERSION declaration and, if this value must be numeric,
use a numeric constraint such as `@GlobalConfigValidation`(numberGreaterThan = -1)
on the VM_METADATA_LAST_REFRESH_VERSION GlobalConfig to enforce valid values and
match other GlobalConfig definitions.
In
`@plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.java`:
- Around line 87-99: The extractOldPrefix logic in NfsVmMetadataExtension
duplicates LocalStorageVmMetadataExtension; create a shared utility (e.g., class
VmMetadataPathUtils) that exposes a static PATH_MARKERS constant and a static
extractOldPrefix(String) implementing the existing logic, then replace the
private extractOldPrefix method in NfsVmMetadataExtension and the one in
LocalStorageVmMetadataExtension to call
VmMetadataPathUtils.extractOldPrefix(path) so both classes reuse the single
implementation.
In `@sdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataAction.java`:
- Line 5: The file contains a redundant import "import org.zstack.sdk.*;" in the
CleanupVmInstanceMetadataAction class; remove that wildcard import since the
class resides in the same package (org.zstack.sdk) and the import is
unnecessary—open the CleanupVmInstanceMetadataAction.java file, delete the line
with "import org.zstack.sdk.*;", keep any other specific imports if present, and
ensure the file still compiles.
In
`@sdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageAction.java`:
- Line 5: Remove the redundant wildcard import line "import org.zstack.sdk.*;"
from the GetVmInstanceMetadataFromPrimaryStorageAction class; since the class is
already in the org.zstack.sdk package, delete that import and verify the file
still compiles (add any explicit imports only if the compiler reports missing
symbols).
In `@sdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataAction.java`:
- Line 5: 该类 UpdateVmInstanceMetadataAction 位于 org.zstack.sdk 包内,顶端的通配符导入语句
"import org.zstack.sdk.*;"
是冗余的;请删除该导入行(或替换为仅需的具体类型导入,如果类引用了其他包的类型),确保类头部不包含未使用的通配符导入以消除冗余。
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 501923f0-db87-49e0-ac86-f06e9891abe7
⛔ Files ignored due to path filters (5)
conf/globalConfig/vm.xmlis excluded by!**/*.xmlconf/persistence.xmlis excluded by!**/*.xmlconf/serviceConfig/primaryStorage.xmlis excluded by!**/*.xmlconf/serviceConfig/vmInstance.xmlis excluded by!**/*.xmlconf/springConfigXml/VmInstanceManager.xmlis excluded by!**/*.xml
📒 Files selected for processing (148)
compute/src/main/java/org/zstack/compute/vm/CleanupVmInstanceMetadataOnPrimaryStorageGC.javacompute/src/main/java/org/zstack/compute/vm/VmExpungeMetadataFlow.javacompute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.javacompute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.javacompute/src/main/java/org/zstack/compute/vm/VmSystemTags.javaconf/db/upgrade/V5.0.0__schema.sqlheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataReply.javaheader/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIDeleteVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIRevertVolumeFromSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIShrinkVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/APIUpdateVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIDeleteVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIRevertVmFromSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIUngroupVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/storage/snapshot/group/APIUpdateVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/tag/APICreateSystemTagMsg.javaheader/src/main/java/org/zstack/header/tag/APICreateSystemTagsMsg.javaheader/src/main/java/org/zstack/header/tag/APIDeleteTagMsg.javaheader/src/main/java/org/zstack/header/tag/APIUpdateSystemTagMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachIsoToVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachL3NetworkToVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIAttachVmNicToVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeInstanceOfferingMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeVmNicNetworkMsg.javaheader/src/main/java/org/zstack/header/vm/APIChangeVmNicStateMsg.javaheader/src/main/java/org/zstack/header/vm/APIConvertTemplatedVmInstanceToVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIConvertVmInstanceToTemplatedVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APICreateVmNicMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmBootModeMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmConsolePasswordMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmHostnameMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmNicMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.javaheader/src/main/java/org/zstack/header/vm/APIDeleteVmStaticIpMsg.javaheader/src/main/java/org/zstack/header/vm/APIDestroyVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIDetachIsoFromVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIDetachL3NetworkFromVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIExpungeVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIMigrateVmMsg.javaheader/src/main/java/org/zstack/header/vm/APIRecoverVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIReimageVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootModeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootOrderMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmBootVolumeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmClockTrackMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmConsolePasswordMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmHostnameMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmQxlMemoryMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmSoundTypeMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.javaheader/src/main/java/org/zstack/header/vm/APISetVmStaticIpMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmInstanceMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmNicDriverMsg.javaheader/src/main/java/org/zstack/header/vm/APIUpdateVmPriorityMsg.javaheader/src/main/java/org/zstack/header/vm/VmInstanceState.javaheader/src/main/java/org/zstack/header/vm/cdrom/APICreateVmCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/cdrom/APISetVmInstanceDefaultCdRomMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEvent.javaheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEventDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsgDoc_zh_cn.groovyheader/src/main/java/org/zstack/header/vm/metadata/MetadataImpact.javaheader/src/main/java/org/zstack/header/vm/metadata/ResourceMetadata.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageMsg.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageReply.javaheader/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataReply.javaheader/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataConstants.javaheader/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataDTO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataCategory.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO_.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataErrors.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathBuildExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.javaheader/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.javaheader/src/main/java/org/zstack/header/vm/metadata/VolumeResourceMetadata.javaheader/src/main/java/org/zstack/header/volume/APIAttachDataVolumeToVmMsg.javaheader/src/main/java/org/zstack/header/volume/APIChangeVolumeStateMsg.javaheader/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotGroupMsg.javaheader/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotMsg.javaheader/src/main/java/org/zstack/header/volume/APIDeleteDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIDetachDataVolumeFromVmMsg.javaheader/src/main/java/org/zstack/header/volume/APIExpungeDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIFlattenVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APIRecoverDataVolumeMsg.javaheader/src/main/java/org/zstack/header/volume/APISyncVolumeSizeMsg.javaheader/src/main/java/org/zstack/header/volume/APIUndoSnapshotCreationMsg.javaheader/src/main/java/org/zstack/header/volume/APIUpdateVolumeMsg.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/APILocalStorageMigrateVolumeMsg.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageHypervisorBackend.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageKvmBackend.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulator.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulatorConfig.javaplugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageBackend.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackendCommands.javaplugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsVmMetadataExtension.javaresourceconfig/src/main/java/org/zstack/resourceconfig/APIDeleteResourceConfigMsg.javaresourceconfig/src/main/java/org/zstack/resourceconfig/APIUpdateResourceConfigMsg.javasdk/src/main/java/SourceClassMap.javasdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataAction.javasdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataResult.javasdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageAction.javasdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageResult.javasdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataAction.javasdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.javasdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageAction.javasdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageResult.javasdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataAction.javasdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataResult.javasdk/src/main/java/org/zstack/sdk/VmMetadataScanEntry.javastorage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.javatestlib/src/main/java/org/zstack/testlib/ApiHelper.groovytestlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovytestlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy
✅ Files skipped from review due to trivial changes (91)
- header/src/main/java/org/zstack/header/vm/APIDeleteVmSshKeyMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmBootModeMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIRevertVolumeFromSnapshotMsg.java
- header/src/main/java/org/zstack/header/tag/APIUpdateSystemTagMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataReply.java
- header/src/main/java/org/zstack/header/vm/APIMigrateVmMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootModeMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmConsolePasswordMsg.java
- header/src/main/java/org/zstack/header/vm/cdrom/APICreateVmCdRomMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeVmNicStateMsg.java
- header/src/main/java/org/zstack/header/tag/APICreateSystemTagsMsg.java
- header/src/main/java/org/zstack/header/vm/APIDestroyVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/cdrom/APISetVmInstanceDefaultCdRomMsg.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/tag/APIDeleteTagMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeVmNicNetworkMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/ResourceMetadata.java
- header/src/main/java/org/zstack/header/volume/APIRecoverDataVolumeMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ScanVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEventDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataCategory.java
- header/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/storage/primary/CleanupVmInstanceMetadataOnPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VolumeResourceMetadata.java
- sdk/src/main/java/org/zstack/sdk/GetVmInstanceMetadataFromPrimaryStorageResult.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/APICreateVmNicMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEventDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/storage/primary/GetVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/APIRecoverVmInstanceMsg.java
- resourceconfig/src/main/java/org/zstack/resourceconfig/APIDeleteResourceConfigMsg.java
- header/src/main/java/org/zstack/header/vm/APIExpungeVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIReimageVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIUpdateVmNicDriverMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmSoundTypeMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmHostnameMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIUngroupVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIUpdateVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/vm/APIConvertTemplatedVmInstanceToVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/APIChangeInstanceOfferingMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmConsolePasswordMsg.java
- header/src/main/java/org/zstack/header/storage/primary/ReadVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootVolumeMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmBootOrderMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIDeleteVolumeSnapshotMsg.java
- sdk/src/main/java/org/zstack/sdk/UpdateVmInstanceMetadataResult.java
- header/src/main/java/org/zstack/header/vm/APISetVmSshKeyMsg.java
- header/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/volume/APIAttachDataVolumeToVmMsg.java
- header/src/main/java/org/zstack/header/volume/APIFlattenVolumeMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIUpdateVmInstanceMetadataEvent.java
- header/src/main/java/org/zstack/header/vm/APIAttachL3NetworkToVmMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataReply.java
- header/src/main/java/org/zstack/header/storage/primary/VmMetadataScanEntry.java
- sdk/src/main/java/org/zstack/sdk/CleanupVmInstanceMetadataResult.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataErrors.java
- header/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataDTO.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO_.java
- conf/db/upgrade/V5.0.0__schema.sql
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyService.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathBuildExtensionPoint.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataResourcePersistExtensionPoint.java
- header/src/main/java/org/zstack/header/volume/APIExpungeDataVolumeMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIRegisterVmInstanceFromMetadataEvent.java
- header/src/main/java/org/zstack/header/vm/metadata/MetadataImpact.java
- header/src/main/java/org/zstack/header/vm/metadata/VmInstanceMetadataConstants.java
- header/src/main/java/org/zstack/header/volume/APIUpdateVolumeMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/UpdateVmInstanceMetadataOnPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReplyDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsgDoc_zh_cn.groovy
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataPathReplacementExtensionPoint.java
- sdk/src/main/java/org/zstack/sdk/VmMetadataScanEntry.java
- sdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageResult.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataFingerprintVO.java
- compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java
- sdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataResult.java
- header/src/main/java/org/zstack/header/vm/APIUpdateVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEvent.java
- header/src/main/java/org/zstack/header/volume/APIDetachDataVolumeFromVmMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataEventDoc_zh_cn.groovy
🚧 Files skipped from review as they are similar to previous changes (39)
- header/src/main/java/org/zstack/header/vm/VmInstanceState.java
- header/src/main/java/org/zstack/header/vm/APISetVmQxlMemoryMsg.java
- header/src/main/java/org/zstack/header/volume/APISyncVolumeSizeMsg.java
- header/src/main/java/org/zstack/header/vm/APIAttachVmNicToVmMsg.java
- header/src/main/java/org/zstack/header/volume/APIDeleteDataVolumeMsg.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/APILocalStorageMigrateVolumeMsg.java
- header/src/main/java/org/zstack/header/volume/APICreateVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmHostnameMsg.java
- header/src/main/java/org/zstack/header/volume/APIUndoSnapshotCreationMsg.java
- header/src/main/java/org/zstack/header/vm/APIConvertVmInstanceToTemplatedVmInstanceMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/APIDeleteVmStaticIpMsg.java
- header/src/main/java/org/zstack/header/storage/primary/RebaseVolumeBackingFileOnPrimaryStorageReply.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIShrinkVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmClockTrackMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIDeleteVolumeSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/vm/APISetVmStaticIpMsg.java
- header/src/main/java/org/zstack/header/volume/APIChangeVolumeStateMsg.java
- header/src/main/java/org/zstack/header/vm/APIAttachIsoToVmInstanceMsg.java
- plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageBackend.java
- header/src/main/java/org/zstack/header/vm/metadata/APIGetVmInstanceMetadataFromPrimaryStorageMsgDoc_zh_cn.groovy
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageSimulatorConfig.java
- header/src/main/java/org/zstack/header/storage/snapshot/group/APIRevertVmFromSnapshotGroupMsg.java
- header/src/main/java/org/zstack/header/storage/snapshot/APIUpdateVolumeSnapshotMsg.java
- header/src/main/java/org/zstack/header/storage/primary/APIScanVmInstanceMetadataFromPrimaryStorageMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/VmUuidFromApiResolver.java
- resourceconfig/src/main/java/org/zstack/resourceconfig/APIUpdateResourceConfigMsg.java
- header/src/main/java/org/zstack/header/vm/metadata/APICleanupVmInstanceMetadataMsg.java
- header/src/main/java/org/zstack/header/tag/APICreateSystemTagMsg.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageHypervisorBackend.java
- testlib/src/main/java/org/zstack/testlib/LocalStorageSpec.groovy
- testlib/src/main/java/org/zstack/testlib/NfsPrimaryStorageSpec.groovy
- plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackendCommands.java
- plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorageKVMBackend.java
- header/src/main/java/org/zstack/header/vm/metadata/VmMetadataDirtyVO.java
- plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageVmMetadataExtension.java
- sdk/src/main/java/SourceClassMap.java
- sdk/src/main/java/org/zstack/sdk/ScanVmInstanceMetadataFromPrimaryStorageAction.java
- sdk/src/main/java/org/zstack/sdk/RegisterVmInstanceFromMetadataAction.java
d1bb696 to
2b82b49
Compare
APIImpact Resolves: ZSV-11559 Change-Id: I6b6a6378627264646d6a76726762736e77787373
bdbbce3 to
1d27049
Compare
APIImpact
Resolves: ZSV-11559
Change-Id: I6b6a6378627264646d6a76726762736e77787373
sync from gitlab !9444