Skip to content

<fix>[volume]: support thirdPartySoftwarePackage#3318

Open
zstack-robot-2 wants to merge 1 commit intofeature-zsv-5.0.0-zmigratefrom
sync/tao.gan/zmigrate-ZSV-1000@@3
Open

<fix>[volume]: support thirdPartySoftwarePackage#3318
zstack-robot-2 wants to merge 1 commit intofeature-zsv-5.0.0-zmigratefrom
sync/tao.gan/zmigrate-ZSV-1000@@3

Conversation

@zstack-robot-2
Copy link
Collaborator

APIImpact

Resolves: ZSV-1

Change-Id: I656979726c736267776c7262716969726874716d

sync from gitlab !9141

@coderabbitai
Copy link

coderabbitai bot commented Feb 9, 2026

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

本 PR 在备份存储域新增多种消息/回复类型并扩展 Ceph 插件以支持文件上传/下载/删除/进度查询、取消与升级包部署,同时在 BackupStorageBase 加入本地消息分发分支;新增多项 SDK 接口、zMigrate 接口、测试辅助方法与 Ceph 模拟器,并扩展许可枚举。

Changes

Cohort / File(s) Summary
Backup storage messages & replies
header/src/main/java/org/zstack/header/storage/backup/CancelDownloadFileOnBackupStorageHostMsg.java, .../CancelDownloadFileOnBackupStorageHostReply.java, .../DeleteFilesOnBackupStorageHostMsg.java, .../DeleteFilesOnBackupStorageHostReply.java, .../GetFileDownloadProgressFromBackupStorageHostMsg.java, .../GetFileDownloadProgressFromBackupStorageHostReply.java, .../UploadFileToBackupStorageHostMsg.java, .../UploadFileToBackupStorageHostReply.java
新增上传/删除/取消下载/查询下载进度相关的消息与回复类,包含 backupStorage/host/task/url/installPath/进度/校验等字段及访问器。
Software upgrade messages & replies
header/src/main/java/org/zstack/header/storage/backup/SoftwareUpgradePackageDeployMsg.java, .../SoftwareUpgradePackageDeployReply.java
新增升级包部署消息与空回复类,消息包含源/目标路径、目标主机 SSH 凭据与脚本路径等字段及访问器。
Ceph backup storage plugin
plugin/ceph/src/main/java/org/zstack/storage/ceph/backup/CephBackupStorageBase.java
新增多种 AgentCommand/AgentResponse 内部类、REST 路径常量并注入 ApiTimeoutManager;实现对新增消息的构造/解析、HTTP 调用、超时与取消处理以及回复映射。
BackupStorageBase handlers
storage/src/main/java/org/zstack/storage/backup/BackupStorageBase.java
新增 5 个受保护的本地消息处理方法(Upload/Delete/GetProgress/SoftwareUpgrade/CancelDownload),并在本地消息路由中加入相应 instanceof 分支,默认委派到 bus.dealWithUnknownMessage(msg)。
SDK: software package actions & results
sdk/src/main/java/org/zstack/sdk/softwarePackage/header/*Upload*, *UploadAndExecute*, *CleanUpgrade*, *CleanUpgradeSoftwarePackageAction.java, *CleanUpgradeSoftwarePackageResult.java
新增多个 SDK Action 与 Result/DTO(上传软件包、上传并执行升级、清理升级等),含 REST 元数据、参数定义、同步/异步调用封装与结果映射。
SDK: zMigrate APIs & results
sdk/src/main/java/org/zstack/sdk/zmigrate/api/GetZMigrateGatewayVmInstancesAction.java, .../GetZMigrateGatewayVmInstancesResult.java, GetZMigrateImagesAction.java, GetZMigrateImagesResult.java, GetZMigrateInfosAction.java, GetZMigrateInfosResult.java
新增 zMigrate 相关 SDK Action 与返回 DTO,提供获取网关 VM、镜像列表与管理信息的 API 封装与 REST 元数据。
SDK: additional license
sdk/src/main/java/org/zstack/sdk/AdditionalLicenseType.java
在枚举中新增许可证类型常量 zmigrate
Test utilities & simulators
testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy, testlib/src/main/java/org/zstack/testlib/CephBackupStorageSpec.groovy
ApiHelper 增加/调整大量 API 封装方法(包括 cleanUpgradeSoftwarePackage);CephBackupStorageSpec 新增 Ceph 备份存储的下载/上传/进度/删除/升级部署模拟器响应。

Sequence Diagram(s)

sequenceDiagram
  participant SDK as "SDK Action"
  participant API as "API Server"
  participant Bus as "Message Bus / BackupStorageBase"
  participant Ceph as "CephBackupStorageBase"
  participant Agent as "Backup Storage Agent"

  SDK->>API: 发起上传/下载/删除/升级 等 REST 请求
  API->>Bus: 构造 NeedReplyMessage / CancelMessage 并发送
  Bus->>Ceph: BackupStorageBase 转发到 CephBackupStorageBase 处理
  Ceph->>Agent: 构造 AgentCommand (Download/Upload/Delete/Progress/Upgrade/Cancel)
  Agent-->>Ceph: 返回 AgentResponse / 进度/状态
  Ceph-->>Bus: 映射为 MessageReply 并回传
  Bus-->>API: API 返回结果给调用方
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 我是小兔提新令,消息与回复排队行,
Ceph 路径开新径,上传下载竞相鸣,
进度与取消细数声,升级脚本悄助攻,
SDK 与测试共欢庆,合并一跳春色盈。

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR标题清晰准确地反映了主要变更内容,即支持第三方软件包(thirdPartySoftwarePackage)功能。
Description check ✅ Passed PR描述与变更相关,提供了问题解决编号(ZSV-1)和来源信息(sync from gitlab !9141),内容与changeset相关。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sync/tao.gan/zmigrate-ZSV-1000@@3

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In
`@plugin/ceph/src/main/java/org/zstack/storage/ceph/backup/CephBackupStorageBase.java`:
- Around line 2174-2206: The DeleteFilesCmd sent via
CephBackupStorageMonBase.httpCall lacks the AgentCommand base fields; before
calling monBase.httpCall in handle(DeleteFilesOnBackupStorageHostMsg) set the
command's base fields (e.g. cmd.fsid = getSelf().getFsid(); cmd.uuid =
mon.getUuid()) so the agent receives fsid/uuid, and apply the same fix to the
other httpCall usages in this class (the other commands used in the ranges
referenced) — ensure each AgentCommand subclass populates fsid and uuid (or the
equivalent base fields) from getSelf() and the mon before calling
monBase.httpCall(...).

In `@sdk/src/main/java/org/zstack/sdk/zmigrate/api/GetZMigrateImagesAction.java`:
- Around line 47-58: In makeResult, rename the abbreviated variables to full
words to improve readability: change parameter res to apiResult, local ret to
result, and local value to resultValue (or similar descriptive names); update
the references inside the method (including the error check, assignment
ret.error, and the getResult call
org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult) so the logic and
null-coalescing behavior remain identical; apply the same renaming pattern to
the other occurrences noted (around the other makeResult-like blocks at the
indicated regions) so all short names (res/ret/value/info) become descriptive
across GetZMigrateImagesAction.

In `@testlib/src/main/java/org/zstack/testlib/CephBackupStorageSpec.groovy`:
- Around line 233-260: The simulator handlers for
CephBackupStorageBase.FILE_UPLOAD_PATH and
CephBackupStorageBase.FILE_UPLOAD_PROGRESS_PATH are returning generic
AgentResponse which mismatches real agents; change the FILE_UPLOAD_PATH handler
to return a CephBackupStorageBase.UploadFileResponse and set its
directUploadPath (and any other expected fields), and change the
FILE_UPLOAD_PROGRESS_PATH handler to return a
CephBackupStorageBase.GetDownloadFileProgressResponse and populate the
progress-related fields so tests see the same shape as real responses; keep the
other simulator handlers as-is.
🧹 Nitpick comments (4)
sdk/src/main/java/org/zstack/sdk/softwarePackage/header/UploadSoftwarePackageToBackupStorageResult.java (1)

3-3: 冗余的同包导入。

SoftwarePackageInventory 与当前类在同一个包 org.zstack.sdk.softwarePackage.header 中,无需显式导入。

♻️ 建议移除冗余导入
 package org.zstack.sdk.softwarePackage.header;
 
-import org.zstack.sdk.softwarePackage.header.SoftwarePackageInventory;
-
 public class UploadSoftwarePackageToBackupStorageResult {
sdk/src/main/java/org/zstack/sdk/zmigrate/api/GetZMigrateGatewayVmInstancesResult.java (1)

14-20: List 类型应添加泛型参数以增强类型安全。

当前 gatewayVmInstances 使用原始类型 java.util.List,缺少泛型参数。虽然此模式在 SDK 中广泛采用(整个 SDK 代码库都遵循此约定),但添加泛型参数(如 List<String>List<?>)可以提高编译时类型检查的严格性。建议与其他 SDK 类统一进行泛型参数升级。

sdk/src/main/java/org/zstack/sdk/softwarePackage/header/UploadAndExecuteSoftwareUpgradePackageResult.java (1)

4-4: 冗余的同包导入语句

SoftwarePackageInventory 与当前类在同一个包 org.zstack.sdk.softwarePackage.header 中,Java 不需要显式导入同包类。

♻️ 建议移除冗余导入
 package org.zstack.sdk.softwarePackage.header;
 
-
-import org.zstack.sdk.softwarePackage.header.SoftwarePackageInventory;
 
 public class UploadAndExecuteSoftwareUpgradePackageResult {
header/src/main/java/org/zstack/header/storage/backup/SoftwareUpgradePackageDeployMsg.java (1)

11-11: 可选建议:考虑使用 Integer 包装类型替代 int。

targetHostSshPort 使用 int 原始类型,默认值为 0。如果需要区分"未设置"和"显式设置为 0"的情况,建议使用 Integer 类型,以便通过 null 检测未设置状态。

♻️ 可选改进
-    private int targetHostSshPort;
+    private Integer targetHostSshPort;

同时需要修改 getter/setter 的返回类型:

-    public int getTargetHostSshPort() {
+    public Integer getTargetHostSshPort() {
         return targetHostSshPort;
     }

-    public void setTargetHostSshPort(int targetHostSshPort) {
+    public void setTargetHostSshPort(Integer targetHostSshPort) {
         this.targetHostSshPort = targetHostSshPort;
     }

Comment on lines 2174 to 2206
@Override
protected void handle(final DeleteFilesOnBackupStorageHostMsg msg) {
DeleteFilesOnBackupStorageHostReply reply = new DeleteFilesOnBackupStorageHostReply();
if (CoreGlobalProperty.UNIT_TEST_ON) {
bus.reply(msg, reply);
return;
}

CephBackupStorageMonVO mon = getSelf().getMons().stream()
.filter(m -> m.getUuid().equals(msg.getBackupStorageHostUuid())).findAny().orElse(null);
if (mon == null) {
reply.setError(operr("failed to find mon with uuid [%s]", msg.getBackupStorageHostUuid()));
bus.reply(msg, reply);
return;
}

DeleteFilesCmd cmd = new DeleteFilesCmd();
cmd.filesPath = msg.getFilesPath();

CephBackupStorageMonBase monBase = new CephBackupStorageMonBase(mon);
monBase.httpCall(DELETE_FILE_PATH, cmd, DeleteFilesResponse.class, new ReturnValueCompletion<DeleteFilesResponse>(msg) {
@Override
public void fail(ErrorCode err) {
reply.setError(err);
bus.reply(msg, reply);
}

@Override
public void success(DeleteFilesResponse rsp) {
bus.reply(msg, reply);
}
});
}
Copy link

@coderabbitai coderabbitai bot Feb 9, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

为指定 mon 的 httpCall 补全 AgentCommand 基础字段。
这三处直接使用 CephBackupStorageMonBase.httpCall(...),不会像 HttpCaller 一样自动填充 fsid/uuid。若 agent 依赖该字段,会导致请求失败或定位错误。建议在发送前显式赋值。

✅ 建议修复
 DeleteFilesCmd cmd = new DeleteFilesCmd();
+cmd.setUuid(self.getUuid());
+cmd.setFsid(getSelf().getFsid());
 cmd.filesPath = msg.getFilesPath();
 GetDownloadFileProgressCmd cmd = new GetDownloadFileProgressCmd();
+cmd.setUuid(self.getUuid());
+cmd.setFsid(getSelf().getFsid());
 cmd.taskUuid = msg.getTaskUuid();
 SoftwareUpgradePackageCmd cmd = new SoftwareUpgradePackageCmd();
+cmd.setUuid(self.getUuid());
+cmd.setFsid(getSelf().getFsid());
 cmd.upgradePackagePath = msg.getUpgradePackagePath();

Also applies to: 2208-2250, 2252-2291

🤖 Prompt for AI Agents
In
`@plugin/ceph/src/main/java/org/zstack/storage/ceph/backup/CephBackupStorageBase.java`
around lines 2174 - 2206, The DeleteFilesCmd sent via
CephBackupStorageMonBase.httpCall lacks the AgentCommand base fields; before
calling monBase.httpCall in handle(DeleteFilesOnBackupStorageHostMsg) set the
command's base fields (e.g. cmd.fsid = getSelf().getFsid(); cmd.uuid =
mon.getUuid()) so the agent receives fsid/uuid, and apply the same fix to the
other httpCall usages in this class (the other commands used in the ranges
referenced) — ensure each AgentCommand subclass populates fsid and uuid (or the
equivalent base fields) from getSelf() and the mon before calling
monBase.httpCall(...).

Copy link
Owner

Choose a reason for hiding this comment

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

Comment from tao.gan:

删除物理机上文件,不需要补全

Copy link

Choose a reason for hiding this comment

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

@MatheMatrix 感谢您的说明!

理解了,如果删除文件的 agent 端点确实不依赖这些字段,那么 DeleteFilesCmd 可以不补全。

不过注意到同一批代码中,GetDownloadFileProgressCmd (Line 2208-2250) 和 SoftwareUpgradePackageCmd (Line 2252-2291) 也采用了相同的直接调用 monBase.httpCall() 的方式,没有经过 HttpCallerprepareCmd() 环节。

请确认:

  1. 这两个命令的 agent 端点是否也不需要 fsid/uuid 字段?
  2. 如果需要,建议在这两处补全字段,保持与代码库中其他 AgentCommand 的一致性

如果这三个操作的 agent 实现都明确不依赖这些字段,可以考虑在代码注释中说明原因,方便后续维护。

Comment on lines +47 to +58
private Result makeResult(ApiResult res) {
Result ret = new Result();
if (res.error != null) {
ret.error = res.error;
return ret;
}

org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult value = res.getResult(org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult.class);
ret.value = value == null ? new org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult() : value;

return ret;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

避免使用缩写变量名以符合命名规范。

ret/res/info 可读性较弱,建议改为完整单词。

♻️ 建议命名修正
-    private Result makeResult(ApiResult res) {
-        Result ret = new Result();
-        if (res.error != null) {
-            ret.error = res.error;
-            return ret;
+    private Result makeResult(ApiResult apiResult) {
+        Result result = new Result();
+        if (apiResult.error != null) {
+            result.error = apiResult.error;
+            return result;
         }
         
-        org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult value = res.getResult(org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult.class);
-        ret.value = value == null ? new org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult() : value; 
-
-        return ret;
+        org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult value = apiResult.getResult(org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult.class);
+        result.value = value == null ? new org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult() : value; 
+
+        return result;
     }
@@
-            public void complete(ApiResult res) {
-                completion.complete(makeResult(res));
+            public void complete(ApiResult apiResult) {
+                completion.complete(makeResult(apiResult));
             }
@@
-        RestInfo info = new RestInfo();
-        info.httpMethod = "GET";
-        info.path = "/zmigrate/images";
-        info.needSession = true;
-        info.needPoll = false;
-        info.parameterName = "";
-        return info;
+        RestInfo restInfo = new RestInfo();
+        restInfo.httpMethod = "GET";
+        restInfo.path = "/zmigrate/images";
+        restInfo.needSession = true;
+        restInfo.needPoll = false;
+        restInfo.parameterName = "";
+        return restInfo;
     }
As per coding guidelines 不允许使用不必要的缩写,如:AbsSchedulerJob、condi、Fu 等。应使用完整单词提升可读性。

Also applies to: 66-69, 82-89

🤖 Prompt for AI Agents
In `@sdk/src/main/java/org/zstack/sdk/zmigrate/api/GetZMigrateImagesAction.java`
around lines 47 - 58, In makeResult, rename the abbreviated variables to full
words to improve readability: change parameter res to apiResult, local ret to
result, and local value to resultValue (or similar descriptive names); update
the references inside the method (including the error check, assignment
ret.error, and the getResult call
org.zstack.sdk.zmigrate.api.GetZMigrateImagesResult) so the logic and
null-coalescing behavior remain identical; apply the same renaming pattern to
the other occurrences noted (around the other makeResult-like blocks at the
indicated regions) so all short names (res/ret/value/info) become descriptive
across GetZMigrateImagesAction.

Comment on lines 233 to 260
simulator(CephBackupStorageBase.FILE_DOWNLOAD_PATH) { HttpEntity<String> entity ->
def rsp = new CephBackupStorageBase.DownloadFileResponse()
rsp.md5sum = "1234567890"
rsp.size = 3L * 1024 * 1024 * 1024
rsp.unzipInstallPath = "/root/zstone-software-package/unzipInstallPath"
rsp.filesSize = [:]
rsp.filesSize.put("/root/zstone-software-package/unzipInstallPath/Gateway_Linux_Server_(Treker).zmigrate.fast.10.1.106.qcow2", 1024L * 1024 * 1024)
rsp.filesSize.put("/root/zstone-software-package/unzipInstallPath/BootImage_for_Linux_(TrekerLite)_10.1.106.qcow2", 1024L * 1024 * 1024)
rsp.filesSize.put("/root/zstone-software-package/unzipInstallPath/BootImage_for_Windows_(TrekerLite)_10.1.106.qcow2", 1024L * 1024 * 1024)
return rsp
}

simulator(CephBackupStorageBase.FILE_UPLOAD_PATH) { HttpEntity<String> entity ->
def rsp = new CephBackupStorageBase.AgentResponse()
return rsp
}
simulator(CephBackupStorageBase.FILE_UPLOAD_PROGRESS_PATH) { HttpEntity<String> entity ->
def rsp = new CephBackupStorageBase.AgentResponse()
return rsp
}
simulator(CephBackupStorageBase.DELETE_FILE_PATH) { HttpEntity<String> entity ->
def rsp = new CephBackupStorageBase.AgentResponse()
return rsp
}
simulator(CephBackupStorageBase.SOFTWARE_UPGRADE_PACKAGE_DEPLOY_PATH) { HttpEntity<String> entity ->
def rsp = new CephBackupStorageBase.AgentResponse()
return rsp
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

模拟器返回类型与真实响应不一致。
FILE_UPLOAD_PATH 期望 UploadFileResponse(含 directUploadPath),FILE_UPLOAD_PROGRESS_PATH 期望 GetDownloadFileProgressResponse(含进度字段)。当前返回 AgentResponse 会导致测试中字段为空,容易掩盖问题。

✅ 建议修复
 simulator(CephBackupStorageBase.FILE_UPLOAD_PATH) { HttpEntity<String> entity ->
-    def rsp = new CephBackupStorageBase.AgentResponse()
+    def rsp = new CephBackupStorageBase.UploadFileResponse()
+    rsp.directUploadPath = "/tmp/direct-upload"
     return rsp
 }
 simulator(CephBackupStorageBase.FILE_UPLOAD_PROGRESS_PATH) { HttpEntity<String> entity ->
-    def rsp = new CephBackupStorageBase.AgentResponse()
+    def rsp = new CephBackupStorageBase.GetDownloadFileProgressResponse()
+    rsp.completed = false
+    rsp.progress = 0
+    rsp.size = 0L
+    rsp.actualSize = 0L
+    rsp.downloadSize = 0L
     return rsp
 }
🤖 Prompt for AI Agents
In `@testlib/src/main/java/org/zstack/testlib/CephBackupStorageSpec.groovy` around
lines 233 - 260, The simulator handlers for
CephBackupStorageBase.FILE_UPLOAD_PATH and
CephBackupStorageBase.FILE_UPLOAD_PROGRESS_PATH are returning generic
AgentResponse which mismatches real agents; change the FILE_UPLOAD_PATH handler
to return a CephBackupStorageBase.UploadFileResponse and set its
directUploadPath (and any other expected fields), and change the
FILE_UPLOAD_PROGRESS_PATH handler to return a
CephBackupStorageBase.GetDownloadFileProgressResponse and populate the
progress-related fields so tests see the same shape as real responses; keep the
other simulator handlers as-is.

@MatheMatrix MatheMatrix force-pushed the sync/tao.gan/zmigrate-ZSV-1000@@3 branch from 19b4a85 to 9906a04 Compare February 9, 2026 12:21
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In
`@sdk/src/main/java/org/zstack/sdk/zmigrate/api/GetZMigrateGatewayVmInstancesResult.java`:
- Around line 6-17: The setters in GetZMigrateGatewayVmInstancesResult use
parameter names identical to the fields (managementVmInstanceUuid,
gatewayVmInstances); rename the parameters (e.g., managementVmInstanceUuidParam
or value, gatewayVmInstancesParam) inside setManagementVmInstanceUuid and
setGatewayVmInstances and assign them to this.managementVmInstanceUuid and
this.gatewayVmInstances respectively to avoid name collision and follow naming
conventions.

In `@testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy`:
- Around line 38617-38641: The cleanUpgradeSoftwarePackage method in ApiHelper
(and similar methods) appears to be manually edited in generated code; revert
any manual changes and regenerate this file from the upstream code generator so
the changes come from the generator rather than hand edits; ensure the generator
source that emits methods like cleanUpgradeSoftwarePackage, the ApiPathTracker
usage and Test.apiPaths population is updated/synced and then re-run the
generator to produce a consistent ApiHelper.groovy output.
🧹 Nitpick comments (5)
sdk/src/main/java/org/zstack/sdk/zmigrate/api/GetZMigrateImagesResult.java (1)

6-6: 建议为 Map 添加泛型参数以增强类型安全。

使用原始类型 java.util.Map 会产生编译器警告,并且缺乏类型安全性。建议指定泛型参数,例如 Map<String, Object> 或更具体的类型。

♻️ 建议的修改
-    public java.util.Map images;
+    public java.util.Map<String, Object> images;

同时更新 getter 和 setter 的签名:

-    public void setImages(java.util.Map images) {
+    public void setImages(java.util.Map<String, Object> images) {
         this.images = images;
     }
-    public java.util.Map getImages() {
+    public java.util.Map<String, Object> getImages() {
         return this.images;
     }
sdk/src/main/java/org/zstack/sdk/softwarePackage/header/UploadSoftwarePackageToBackupStorageResult.java (1)

3-3: 冗余的同包导入

SoftwarePackageInventory 与当前类在同一个包 org.zstack.sdk.softwarePackage.header 中,无需显式导入。

♻️ 建议移除冗余导入
 package org.zstack.sdk.softwarePackage.header;
 
-import org.zstack.sdk.softwarePackage.header.SoftwarePackageInventory;
-
 public class UploadSoftwarePackageToBackupStorageResult {
sdk/src/main/java/org/zstack/sdk/softwarePackage/header/CleanUpgradeSoftwarePackageAction.java (1)

34-38: 原始类型 List 缺少泛型参数

systemTagsuserTags 使用了原始的 java.util.List 类型,建议添加泛型参数以提高类型安全性。不过考虑到这与项目中其他 SDK Action 类的风格保持一致,可作为后续统一优化的改进点。

♻️ 建议添加泛型参数
     `@Param`(required = false)
-    public java.util.List systemTags;
+    public java.util.List<String> systemTags;

     `@Param`(required = false)
-    public java.util.List userTags;
+    public java.util.List<String> userTags;
sdk/src/main/java/org/zstack/sdk/softwarePackage/header/UploadSoftwarePackageToBackupStorageAction.java (1)

46-53: 原始类型 List 缺少泛型参数

tagUuidssystemTagsuserTags 使用了原始的 java.util.List 类型。与前一个文件相同的建议,可考虑添加泛型参数。

♻️ 建议添加泛型参数
     `@Param`(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false)
-    public java.util.List tagUuids;
+    public java.util.List<String> tagUuids;

     `@Param`(required = false)
-    public java.util.List systemTags;
+    public java.util.List<String> systemTags;

     `@Param`(required = false)
-    public java.util.List userTags;
+    public java.util.List<String> userTags;
sdk/src/main/java/org/zstack/sdk/zmigrate/api/GetZMigrateGatewayVmInstancesResult.java (1)

14-19: List 增加泛型以提升类型安全

当前使用了原始类型 List,建议补充具体泛型类型。根据字段名称 gatewayVmInstances,该列表很可能存储 VM 实例标识符(如 String UUID)或对象。如无法确定具体类型,至少应使用 List<?> 作为类型安全的最小保障。

♻️ 建议修改
-    public java.util.List gatewayVmInstances;
-    public void setGatewayVmInstances(java.util.List gatewayVmInstances) {
+    public java.util.List<?> gatewayVmInstances;
+    public void setGatewayVmInstances(java.util.List<?> gatewayVmInstances) {
         this.gatewayVmInstances = gatewayVmInstances;
     }
-    public java.util.List getGatewayVmInstances() {
+    public java.util.List<?> getGatewayVmInstances() {
         return this.gatewayVmInstances;
     }

Comment on lines +6 to +17
public java.lang.String managementVmInstanceUuid;
public void setManagementVmInstanceUuid(java.lang.String managementVmInstanceUuid) {
this.managementVmInstanceUuid = managementVmInstanceUuid;
}
public java.lang.String getManagementVmInstanceUuid() {
return this.managementVmInstanceUuid;
}

public java.util.List gatewayVmInstances;
public void setGatewayVmInstances(java.util.List gatewayVmInstances) {
this.gatewayVmInstances = gatewayVmInstances;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

参数名与成员变量同名,违反命名规范

setter 参数与字段同名,按规范需要避免,建议改成不同的参数名以减少歧义。

🔧 建议修改
-    public void setManagementVmInstanceUuid(java.lang.String managementVmInstanceUuid) {
-        this.managementVmInstanceUuid = managementVmInstanceUuid;
+    public void setManagementVmInstanceUuid(java.lang.String managementVmInstanceUuidValue) {
+        this.managementVmInstanceUuid = managementVmInstanceUuidValue;
     }
@@
-    public void setGatewayVmInstances(java.util.List gatewayVmInstances) {
-        this.gatewayVmInstances = gatewayVmInstances;
+    public void setGatewayVmInstances(java.util.List gatewayVmInstancesValue) {
+        this.gatewayVmInstances = gatewayVmInstancesValue;
     }

As per coding guidelines: 避免在父子类或同一代码块中出现相同名字的成员或局部变量,防止混淆。

🤖 Prompt for AI Agents
In
`@sdk/src/main/java/org/zstack/sdk/zmigrate/api/GetZMigrateGatewayVmInstancesResult.java`
around lines 6 - 17, The setters in GetZMigrateGatewayVmInstancesResult use
parameter names identical to the fields (managementVmInstanceUuid,
gatewayVmInstances); rename the parameters (e.g., managementVmInstanceUuidParam
or value, gatewayVmInstancesParam) inside setManagementVmInstanceUuid and
setGatewayVmInstances and assign them to this.managementVmInstanceUuid and
this.gatewayVmInstances respectively to avoid name collision and follow naming
conventions.

@MatheMatrix MatheMatrix force-pushed the sync/tao.gan/zmigrate-ZSV-1000@@3 branch 2 times, most recently from ddb9e36 to 9c184d2 Compare February 9, 2026 13:08
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@sdk/src/main/java/org/zstack/sdk/softwarePackage/header/CleanUpgradeSoftwarePackageAction.java`:
- Around line 94-102: The REST path in
CleanUpgradeSoftwarePackageAction.getRestInfo currently uses the singular
"/software-package/upgrade/{uuid}" and should be changed to the plural form to
match the module convention and UploadAndExecuteSoftwareUpgradePackageAction;
update the RestInfo.path value in getRestInfo of class
CleanUpgradeSoftwarePackageAction to "/software-packages/upgrade/{uuid}" so API
naming is consistent across actions.
🧹 Nitpick comments (3)
sdk/src/main/java/org/zstack/sdk/zmigrate/api/GetZMigrateGatewayVmInstancesAction.java (1)

28-33: 建议为标签列表添加泛型,提升类型安全。

使用原始 List 会丢失编译期类型检查,建议改为 List。

♻️ 建议修改
-    public java.util.List systemTags;
+    public java.util.List<String> systemTags;

-    public java.util.List userTags;
+    public java.util.List<String> userTags;
sdk/src/main/java/org/zstack/sdk/softwarePackage/header/UploadSoftwarePackageToBackupStorageAction.java (1)

46-53: List 字段使用了原始类型。

tagUuidssystemTagsuserTags 字段使用了原始 List 类型而非泛型类型。由于这是自动生成的 SDK 代码,此问题可忽略,但如果手动维护,建议使用 List<String> 以提高类型安全性。

sdk/src/main/java/org/zstack/sdk/softwarePackage/header/CleanUpgradeSoftwarePackageAction.java (1)

28-29: uuid 参数缺少 maxLength 约束。

uuid 字段标记为 required = true,但未指定 maxLength。其他类似的 Action 类中,UUID 字段通常会有长度限制(如 32 或 36 字符)。建议确认是否需要添加长度约束以保持一致性。

Comment on lines 94 to 102
protected RestInfo getRestInfo() {
RestInfo info = new RestInfo();
info.httpMethod = "DELETE";
info.path = "/software-package/upgrade/{uuid}";
info.needSession = true;
info.needPoll = true;
info.parameterName = "";
return info;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 搜索服务端 API 定义中的 software-package 相关路径
echo "=== 搜索服务端 API 定义 ==="
rg -n "software-package|upgrade" --type java -g '!sdk/**' -i | grep -E "(RestRequest|path)" | head -20

# 搜索类似的清理/操作端点
echo -e "\n=== 搜索类似的清理操作端点 ==="
rg -n "@RestRequest.*DELETE" --type java -A 2 | head -40

# 查找 header 文件中的 API 定义
echo -e "\n=== 查找 software-package 相关的 header 定义 ==="
find . -path "*/header/*" -name "*Software*" -type f | head -20

Repository: MatheMatrix/zstack

Length of output: 3124


🏁 Script executed:

#!/bin/bash
# 查看完整的 CleanUpgradeSoftwarePackageAction 所在目录结构
echo "=== CleanUpgradeSoftwarePackageAction 文件所在目录 ==="
find . -name "CleanUpgradeSoftwarePackageAction.java" -type f

# 查找对应的消息类(server-side)
echo -e "\n=== 查找对应的服务端消息类 ==="
find . -name "*CleanUpgradeSoftwarePackage*" -type f | grep -v sdk | grep -v target

# 查找 UploadSoftwarePackageToBackupStorageAction 对比
echo -e "\n=== 查找上传操作进行对比 ==="
find . -name "*UploadSoftwarePackageToBackupStorage*" -type f

Repository: MatheMatrix/zstack

Length of output: 460


🏁 Script executed:

#!/bin/bash
# 检查 UploadSoftwarePackageToBackupStorageAction 的实际路径
echo "=== UploadSoftwarePackageToBackupStorageAction 路径 ==="
grep -n "path.*software" ./sdk/src/main/java/org/zstack/sdk/softwarePackage/header/UploadSoftwarePackageToBackupStorageAction.java

# 检查 CleanUpgradeSoftwarePackageAction 的路径
echo -e "\n=== CleanUpgradeSoftwarePackageAction 路径 ==="
grep -n "path.*software" ./sdk/src/main/java/org/zstack/sdk/softwarePackage/header/CleanUpgradeSoftwarePackageAction.java

# 搜索所有 software 相关的 API 消息定义(server-side)
echo -e "\n=== 搜索所有 software 相关的服务端 API 消息 ==="
find . -path "*/header/*" -type f -name "*.java" ! -path "*/sdk/*" | xargs grep -l -i "software.*msg\|software.*message" 2>/dev/null | head -10

# 检查是否有 CleanUpgrade 相关的服务端定义
echo -e "\n=== 查找 CleanUpgrade 服务端定义 ==="
find . -path "*/header/*" -type f -name "*.java" ! -path "*/sdk/*" | xargs grep -l "CleanUpgrade\|CleanUpgradeSoftware" 2>/dev/null

Repository: MatheMatrix/zstack

Length of output: 546


🏁 Script executed:

#!/bin/bash
# 对比所有软件包相关操作的 REST 路径
echo "=== 所有 softwarePackage 相关操作的 REST 路径 ==="
grep -r "path = " ./sdk/src/main/java/org/zstack/sdk/softwarePackage/header/ --include="*.java" | grep -E "Action.java" | sed 's/.*path = "//;s/".*//'

# 查找其他 upgrade 相关的路径模式
echo -e "\n=== 其他 upgrade 相关的路径 ==="
rg "path.*upgrade" --type java -A 1 -B 1 | head -30

Repository: MatheMatrix/zstack

Length of output: 1356


🏁 Script executed:

#!/bin/bash
# 查找服务端的 API 消息类定义,看是否存在对应的 CleanUpgrade 定义
echo "=== 在 header 文件夹中查找任何 upgrade 相关的 API 消息 ==="
find ./header -type f -name "*Upgrade*.java" | grep -E "Msg|Message" | head -20

# 查看 SoftwareUpgradePackageDeployMsg 的内容
echo -e "\n=== 查看 SoftwareUpgradePackageDeployMsg 内容 ==="
head -20 ./header/src/main/java/org/zstack/header/storage/backup/SoftwareUpgradePackageDeployMsg.java

# 查找任何包含 clean 或 remove upgrade 的定义
echo -e "\n=== 查找清理升级包的服务端定义 ==="
rg -n "CleanUpgrade|RemoveUpgrade|DeleteUpgrade" --type java | grep -v sdk | head -20

Repository: MatheMatrix/zstack

Length of output: 969


🏁 Script executed:

#!/bin/bash
# 检查 UploadAndExecuteSoftwareUpgradePackageAction 是否是类似的操作
echo "=== UploadAndExecuteSoftwareUpgradePackageAction 完整路径 ==="
sed -n '94,104p' ./sdk/src/main/java/org/zstack/sdk/softwarePackage/header/UploadAndExecuteSoftwareUpgradePackageAction.java

# 查看所有 software-package 开头的路径
echo -e "\n=== 所有以 /software-package 开头的路径(singular)==="
grep -r "path = \"/software-package" ./sdk/src/main/java/org/zstack/sdk/softwarePackage/ | sed 's/.*path = "//;s/".*//' | sort -u

# 查看所有 /software-packages 开头的路径(plural)
echo -e "\n=== 所有以 /software-packages 开头的路径(plural)==="
grep -r "path = \"/software-packages" ./sdk/src/main/java/org/zstack/sdk/softwarePackage/ | sed 's/.*path = "//;s/".*//' | sort -u

Repository: MatheMatrix/zstack

Length of output: 962


REST 路径命名不一致。

当前路径 /software-package/upgrade/{uuid} 使用了单数形式,但同一模块中 UploadAndExecuteSoftwareUpgradePackageAction 使用的是 /software-packages/backup-storage/{uuid}/upgrade(复数形式)。

根据编码规范:"path: 针对资源使用复数形式",建议统一使用复数形式 /software-packages/upgrade/{uuid} 以保持 API 一致性。

建议修改
     protected RestInfo getRestInfo() {
         RestInfo info = new RestInfo();
         info.httpMethod = "DELETE";
-        info.path = "/software-package/upgrade/{uuid}";
+        info.path = "/software-packages/upgrade/{uuid}";
         info.needSession = true;
         info.needPoll = true;
         info.parameterName = "";
         return info;
     }
🤖 Prompt for AI Agents
In
`@sdk/src/main/java/org/zstack/sdk/softwarePackage/header/CleanUpgradeSoftwarePackageAction.java`
around lines 94 - 102, The REST path in
CleanUpgradeSoftwarePackageAction.getRestInfo currently uses the singular
"/software-package/upgrade/{uuid}" and should be changed to the plural form to
match the module convention and UploadAndExecuteSoftwareUpgradePackageAction;
update the RestInfo.path value in getRestInfo of class
CleanUpgradeSoftwarePackageAction to "/software-packages/upgrade/{uuid}" so API
naming is consistent across actions.

@MatheMatrix MatheMatrix force-pushed the sync/tao.gan/zmigrate-ZSV-1000@@3 branch 10 times, most recently from 9cb785d to ed7009d Compare February 10, 2026 03:40
@MatheMatrix
Copy link
Owner

Comment from ye.zou:

Code Review Summary (AI-Assisted)

Verdict: CONDITIONAL - 修复 Critical 问题后可合并

Critical (3)

  1. SSH密码明文传输 - SoftwareUpgradePackageDeployMsg.java

    • targetHostSshPassword 虽有 @NoLogging,但通过 CloudBus 消息明文传递
    • 建议参考 AddKVMHostMsg 使用加密机制
  2. 缺少输入验证 - UploadFileToBackupStorageHostMsg.java

    • urlinstallPath 无验证,可能导致 path traversal 或 URL scheme 滥用
    • 建议添加路径白名单和 scheme 限制
  3. 批量删除无保护 - DeleteFilesOnBackupStorageHostMsg.java

    • filesPath 列表无大小限制,无路径白名单
    • 建议限制最大删除数量,验证路径在安全目录内

Major (3)

  1. 消息路由注册 - 确认 CephBackupStorageBaseBackupStorageBase 中已注册所有新消息的处理方法
  2. CancelDownloadFileOnBackupStorageHostMsg - 缺少 taskUuid 字段用于指定取消目标
  3. Commit message - scope 为 volume 但实际改的是 backup storage,type 用了 fix 但这是新功能

Minor

  • 消息类命名风格不统一
  • Reply 类字段过多,建议拆分或添加注释

Review by AI Assistant (Claude) - 请作者确认实现文件中的路径验证和消息处理逻辑

@ZStack-Robot
Copy link
Collaborator

Comment from tao.gan:

1 SSH密码明文传输
1)目前场景仅支持 mn 日志不展示密码。明文传输密码问题,暂不处理

2 缺少输入验证

url 有 scheme 限制

installPath 在 api 中已做校验

3 批量删除无保护

底层删除文件使用 linux.rm_dir_force ,有白名单

4 消息路由注册

1)正常的使用方式

5 CancelDownloadFileOnBackupStorageHostMsg

取消的 job 是 api id,不需要 taskUuid

6 Commit message

type 和 volume 是自动生成的

@MatheMatrix MatheMatrix force-pushed the sync/tao.gan/zmigrate-ZSV-1000@@3 branch 4 times, most recently from 9dd9ec8 to 104ce68 Compare February 11, 2026 14:48
@MatheMatrix
Copy link
Owner

Comment from ye.zou:

Code Review — zstack !9141

Reviewer: AI Code Review Bot | Verdict: REQUEST CHANGES

[CRITICAL] Command injection via SSH parameters to agent

File: CephBackupStorageBase.javaSoftwareUpgradePackageCmd

SSH credentials and script paths passed to the Python agent without validation. The agent then interpolates them into sshpass/ssh/scp shell commands.

Fix: Add input validation before building the command:

  • IP: regex ^[\d.]+$
  • Username: regex ^[a-zA-Z0-9._-]+$
  • Script path: must be absolute, no .., alphanumeric + /._- only

[CRITICAL] Path traversal in file download/upload

File: CephBackupStorageBase.javahandle(UploadFileToBackupStorageHostMsg)

installPath used without path traversal validation. ../../etc/shadow could write to arbitrary locations.

Fix: Validate installPath — must be absolute, must not contain ...

[HIGH] Null safety on getMons().stream()

File: CephBackupStorageBase.java — multiple handler methods

getSelf().getMons() may return null → NPE on .stream(). Appears at lines ~2177, 2213, 2254, 2293.

Fix: Add if (getSelf().getMons() == null || getSelf().getMons().isEmpty()) guard.

[HIGH] Missing URL scheme whitelist

File: CephBackupStorageBase.java

After extracting scheme from URL, no whitelist validation. Only http/https/ftp/file should be allowed.

[MEDIUM] @NoLogging may not prevent password in error stack traces

File: SoftwareUpgradePackageCmd.targetHostSshPassword


5 issues total (2 CRITICAL, 2 HIGH, 1 MEDIUM). Please fix CRITICAL and HIGH before merge.

@zstack-robot-1
Copy link
Collaborator

Comment from tao.gan:

2 Path traversal in file download/upload
api 的 isntall 已经做了校验
image

@MatheMatrix MatheMatrix force-pushed the sync/tao.gan/zmigrate-ZSV-1000@@3 branch 3 times, most recently from f64341a to 4fac778 Compare February 12, 2026 12:38
@zstack-robot-1
Copy link
Collaborator

Comment from ye.zou:

Code Review: zstackio/zstack MR !9141

Feature: thirdPartySoftwarePackage support
Verdict: CONDITIONAL — 修复以下问题后可合并


🔴 Critical (必须修复)

1. NPE 风险 — backupStorageHostUuid 可能为 null
CephBackupStorageBase.java 中多处 mon 查找逻辑:

mons.stream().filter(m -> m.getUuid().equals(msg.getBackupStorageHostUuid())).findAny().orElse(null);

如果 msg.getBackupStorageHostUuid() 为 null,.equals() 会抛 NPE。
建议改为 Objects.equals() 或提前判空。

2. URL scheme 空字符串未校验
CephBackupStorageBase.java 中 scheme 只检查了 null,未检查空字符串:

if (scheme == null) { ... }
cmd.urlScheme = scheme; // scheme 可能是 ""

建议: if (scheme == null || scheme.isEmpty())

3. SSH 密码 @nologging 注解缺少 type
SoftwareUpgradePackageDeployMsg.java@NoLogging 未指定 type = NoLogging.Type.Password,建议补全。


🟡 Major (强烈建议修复)

4. 新 Message 类缺少输入验证
UploadFileToBackupStorageHostMsg 等新消息类的 urlinstallPathfilesPath 字段没有输入校验:

  • url 应验证格式
  • installPath 需防路径穿越 (../../)
  • filesPath 列表应限制最大元素数量

5. 大文件操作 timeout 策略
新增的下载/上传操作使用全局 timeout,大软件包可能超时。建议支持自定义 timeout 或根据操作类型调整。

6. Response vs Reply 字段命名不一致
Agent Response 用 directUploadPath,Java Reply 用 directUploadUrl,Path vs URL 易混淆,建议统一。


🔵 Minor

  • BackupStorageBase.java 新增的 5 个 handle() 默认实现都调用 bus.dealWithUnknownMessage(msg),建议加注释说明需子类覆盖
  • 多处 if (CoreGlobalProperty.UNIT_TEST_ON) 跳过逻辑重复,可抽取为通用方法
  • DeleteFilesCmd.filesPath 缺少 public 访问修饰符

🤖 AI Code Review

@MatheMatrix
Copy link
Owner

Comment from tao.gan:

1 NPE 风险

已修改

2 URL scheme 空字符串未校

已修改

3 SSH 密码 @nologging 注解缺少 type

现有用法,不需要增加 type

4 新 Message 类缺少输入验证

为内部消息,这类消息的参数在api中已校验

5 大文件操作 timeout 策略

上传文件超时时间由 agent 处理,不需要 控制面设置超时

6 Response vs Reply

同一改为 directUploadUrl

7 BackupStorageBase.java 新增的 5 个 handle() 默认实现都调用 bus.dealWithUnknownMessage(msg),建议加注释说明需子类覆盖

表示消息目前进 重载 此函数的子类支持处理此逻辑。

8 多处 if (CoreGlobalProperty.UNIT_TEST_ON) 跳过逻辑重复,可抽取为通用方法

运行case中不执行相关逻辑的通过做法

  • DeleteFilesCmd.filesPath 缺少 public 访问修饰符

已修改

APIImpact

Resolves: ZSV-1000

Change-Id: I656979726c736267776c7262716969726874716d
@MatheMatrix MatheMatrix force-pushed the sync/tao.gan/zmigrate-ZSV-1000@@3 branch from 4fac778 to 78a5433 Compare February 14, 2026 02:18
@zstack-robot-1
Copy link
Collaborator

Comment from gitlab:

自上次添加REVIEWED标签(2026-02-12 22:53:09.000Z)后, 有新的COMMIT更新(2026-02-14 10:18:03.007Z), 所以移除了REVIEWED标签

@ZStack-Robot
Copy link
Collaborator

Comment from ye.zou:

Code Review: zstackio/zstack MR !9141

Branch: zmigrate-ZSV-1000@@3feature-zsv-5.0.0-zmigrate
Files changed: 33 files (14 core, 3 config, 13 SDK, 3 test)
Verdict: ⚠️ CONDITIONAL — 需修复安全和 NPE 问题后合并


🔴 CRITICAL (必须修复)

1. CephBackupStorageBase.java:2149 — NPE 风险
rsp.handleMon 可能为 null,直接调用 getMonUuid() 会 NPE。handle(UploadFileToBackupStorageHostMsg) 的两个分支都存在此问题。

// 修复建议:
if (rsp.handleMon != null) {
    reply.setBackupStorageHostUuid(rsp.handleMon.getMonUuid());
}

2. CephBackupStorageBase.java:2183 — SSH 密码明文传输
targetHostSshPassword 虽标记 @NoLogging,但通过 HTTP 明文传输到 agent。建议使用加密通道或 SSH Key 认证。

3. SoftwareUpgradePackageCmd — 缺少输入校验
targetHostIp、路径等参数直接传递到 SSH 命令,未在 Java 端做校验。虽然 agent 端 (sshValidation.py) 有验证,但 defense-in-depth 要求 Java 端也应验证:

  • IP 格式校验
  • 路径非空 + 无 .. 遍历
  • 空值检查

4. CephBackupStorageBase.java:2138 — URL Scheme 未白名单化
仅检查 scheme 是否存在,未限制为 http/https/uploadfile://ftp:// 等可能导致 SSRF。


🟡 MAJOR (强烈建议)

  • DeleteFilesOnBackupStorageHostMsg: filesPath = new ArrayList<>() 初始化与其他消息类不一致
  • BackupStorageBase.java:295: 新消息处理插入到已有消息之间,破坏逻辑分组
  • 新 API Msg 类缺少 @APIParam(required=true)

🔵 MINOR

  • DeleteFilesCmd.filesPath 命名应为 filePaths
  • URL 解析逻辑可提取公共方法
  • KVMSimulator.groovy 仅模拟上传,未覆盖下载/删除/进度查询
  • errorCodes/SoftwarePackagePlugin.xml 错误码 ID 从 2000 改为 1000,需说明原因

✅ 做得好

  • directUploadPathdirectUploadUrl 命名修复正确
  • @NoLogging 正确应用于敏感字段
  • 消息设计符合 ZStack 框架规范

Review by AI Code Reviewer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants