Skip to content

<fix>[vm]: improve error messages for backup storage selection failures#3396

Open
zstack-robot-1 wants to merge 1 commit into5.5.12from
sync/yaohua.wu/bugfix/ZSTAC-65467
Open

<fix>[vm]: improve error messages for backup storage selection failures#3396
zstack-robot-1 wants to merge 1 commit into5.5.12from
sync/yaohua.wu/bugfix/ZSTAC-65467

Conversation

@zstack-robot-1
Copy link
Collaborator

sync from gitlab !9244

selection failures during ISO attach and VM creation

When VM image or ISO backup storage selection fails,
the error messages previously only stated that no
suitable backup storage was found, without providing
diagnostic details about the actual state of backup
storage resources.

1. Why is this change necessary?
Users encountering backup storage selection failures
had no visibility into the root cause. The error
messages did not indicate which backup storages the
image/ISO was on, their connection status, or which
backup storages were attached to the zone, making
troubleshooting difficult.

2. How does it address the problem?
Added diagnostic helper methods to both
VmDownloadIsoFlow and VmImageSelectBackupStorageFlow
that query and format backup storage state info.
Error messages now include: (a) which backup storages
hold the image/ISO with their status, (b) which
backup storages are attached to the zone with their
status, and (c) actionable suggestions. Also added
dedicated error codes with i18n support for all 10
locales.

3. Are there any side effects?
None. Changes only affect error-path diagnostics.
Normal backup storage selection logic is unchanged.

# Summary of changes (by module):
- compute: add diagnostic info to error messages in
  VmDownloadIsoFlow and VmImageSelectBackupStorageFlow
- conf/i18n: add 4 new error codes (10084-10087)
  across all 10 locale JSON files

Related: ZSTAC-65467
Change-Id: Idbfdaa2b97792a46a29c25b077d990a51f6e1df8
@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

概述

在两个虚拟机工作流类中添加了私有辅助方法,用于查询备份存储映射关系并生成格式化的状态信息字符串,同时使用这些信息增强了备份存储不可用场景下的错误提示信息,提供更详细的诊断上下文。

变更内容

逻辑分组 / 文件 变更摘要
备份存储信息查询方法
compute/src/main/java/org/zstack/compute/vm/VmDownloadIsoFlow.java, compute/src/main/java/org/zstack/compute/vm/VmImageSelectBackupStorageFlow.java
新增两个私有辅助方法 getImageBackupStorageInfo(imageUuid)getZoneBackupStorageInfo(zoneUuid),分别查询镜像级别和区域级别的备份存储映射,返回格式化的存储名称和状态字符串。
错误信息增强
compute/src/main/java/org/zstack/compute/vm/VmDownloadIsoFlow.java, compute/src/main/java/org/zstack/compute/vm/VmImageSelectBackupStorageFlow.java
当备份存储不可用时,将简洁的错误提示替换为包含ISO/镜像名称、UUID、区域UUID以及备份存储查询结果的详细错误信息,增强诊断能力。
依赖导入补充
compute/src/main/java/org/zstack/compute/vm/VmDownloadIsoFlow.java, compute/src/main/java/org/zstack/compute/vm/VmImageSelectBackupStorageFlow.java
新增 BackupStorageStatus、javax.persistence.Tuple、Optional 和 Collectors 等相关导入,支持新增方法的功能实现。

预估审核工作量

🎯 2 (Simple) | ⏱️ ~12 分钟

庆祝诗

🐰 备份存储无处藏,
查询方法显真章,
错误信息细致详,
诊断线索亮堂堂,
兔兔代码更闪亮!✨

🚥 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 标题遵循了所需的 [scope]: 格式,长度为71个字符,未超过72字符限制,并清晰准确地总结了PR的主要变更内容。
Description check ✅ Passed PR描述虽然简洁,但与变更集相关,说明了这是来自GitLab的同步,与代码改进错误信息的目的相符。

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sync/yaohua.wu/bugfix/ZSTAC-65467

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

@ZStack-Robot
Copy link
Collaborator

Comment from yaohua.wu:

Review: MR !9244 — ZSTAC-65467

Jira: 创建vm时镜像位置错误,创建vm失败报错需要优化

Summary

MR enriches error messages in 4 backup storage selection failure paths (VmDownloadIsoFlow and VmImageSelectBackupStorageFlow) with diagnostic context: image/ISO's actual backup storage list with status, zone's attached backup storage list with status, and actionable suggestions. Also adds dedicated i18n error codes (10084-10087) across all 10 locales.

Review Findings

No Critical or Warning issues found.

Suggestion

  1. [VmDownloadIsoFlow.java:49,65] Code duplicationgetImageBackupStorageInfo() and getZoneBackupStorageInfo() are duplicated verbatim between VmDownloadIsoFlow and VmImageSelectBackupStorageFlow. Consider extracting to a shared utility (e.g., static methods on ImageBackupStorageSelector or a new helper class) to reduce maintenance burden. However, given both classes are @Configurable Flow classes and the methods are small, the duplication is acceptable for now.

Checklist

  • Error codes 10084-10087 defined in CloudOperationsErrorCode.java
  • i18n entries added to all 10 locale JSON files
  • Format string %s parameter counts consistent across en_US (5,5,3,5) and zh_CN (5,5,3,5) — verified all locales match
  • Diagnostic queries only execute in error paths — zero performance impact on happy path
  • Error codes preserved (no breaking change)
  • isoName null-guarded with Optional.ofNullable(...).orElse(isoImageUuid) in findIsoBsUuidInTheZone
  • No upstream freshness issues — branch is at upstream/5.5.12 HEAD

Verdict: APPROVED


🤖 Robot Reviewer

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

🤖 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/VmDownloadIsoFlow.java`:
- Around line 54-55: The new code in VmDownloadIsoFlow creates a
TypedQuery<Tuple> directly (dbf.getEntityManager().createQuery(sql, Tuple.class)
and q.setParameter("imageUuid", imageUuid)); replace these direct TypedQuery
usages with the project's unified DB query wrapper (e.g., SimpleQuery/SQLBatch
or the DbFacade helper methods used elsewhere) so queries follow the
repository/DB facade pattern: locate the sql and imageUuid usage in
VmDownloadIsoFlow and rewrite the two query sites (the Tuple-typed query at both
additions) to use the project's standard query helper (passing the SQL and
parameter map) instead of instantiating TypedQuery directly.

In
`@compute/src/main/java/org/zstack/compute/vm/VmImageSelectBackupStorageFlow.java`:
- Around line 167-168: Replace the direct JPA TypedQuery usage (the local
variable q created with dbf.getEntityManager().createQuery and
q.setParameter("imageUuid", ...)) inside VmImageSelectBackupStorageFlow with the
project's Q/QueryMore query API; build a query starting from
Q.New(BackupStorageVO.class, ImageBackupStorageRefVO.class) (or equivalent
QueryMore) to add the join/filter on ImageBackupStorageRefVO.imageUuid, select
the same columns (or tuples) previously requested, and call listTuple() (or the
QueryMore equivalent) to fetch results—remove the TypedQuery instantiation and
parameter binding and mirror the original selection/where logic using
Q/QueryMore methods.

ℹ️ Review info

Configuration used: Path: http://open.zstack.ai:20001/code-reviews/zstack-cloud.yaml (via .coderabbit.yaml)

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2442f28 and 6d57e88.

⛔ Files ignored due to path filters (10)
  • conf/i18n/globalErrorCodeMapping/global-error-de-DE.json is excluded by !**/*.json
  • conf/i18n/globalErrorCodeMapping/global-error-en_US.json is excluded by !**/*.json
  • conf/i18n/globalErrorCodeMapping/global-error-fr-FR.json is excluded by !**/*.json
  • conf/i18n/globalErrorCodeMapping/global-error-id-ID.json is excluded by !**/*.json
  • conf/i18n/globalErrorCodeMapping/global-error-ja-JP.json is excluded by !**/*.json
  • conf/i18n/globalErrorCodeMapping/global-error-ko-KR.json is excluded by !**/*.json
  • conf/i18n/globalErrorCodeMapping/global-error-ru-RU.json is excluded by !**/*.json
  • conf/i18n/globalErrorCodeMapping/global-error-th-TH.json is excluded by !**/*.json
  • conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json is excluded by !**/*.json
  • conf/i18n/globalErrorCodeMapping/global-error-zh_TW.json is excluded by !**/*.json
📒 Files selected for processing (2)
  • compute/src/main/java/org/zstack/compute/vm/VmDownloadIsoFlow.java
  • compute/src/main/java/org/zstack/compute/vm/VmImageSelectBackupStorageFlow.java

Comment on lines +54 to +55
TypedQuery<Tuple> q = dbf.getEntityManager().createQuery(sql, Tuple.class);
q.setParameter("imageUuid", imageUuid);
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:

# First, let's find and examine the specific file
fd -t f "VmDownloadIsoFlow.java" --exec wc -l {} \;

Repository: MatheMatrix/zstack

Length of output: 134


🏁 Script executed:

# Read the file content, focusing on lines around 54-55 and 70-71
fd -t f "VmDownloadIsoFlow.java" --exec cat -n {} \; | head -100

Repository: MatheMatrix/zstack

Length of output: 5244


🏁 Script executed:

# Search for TypedQuery usage patterns in the codebase to understand if it's discouraged
rg "TypedQuery" -t java --max-count 20 -B 2 -A 2

Repository: MatheMatrix/zstack

Length of output: 50375


🏁 Script executed:

# Look for repository query encapsulation patterns
rg "repository|Repository" -t java compute/src/main/java/org/zstack/compute/vm/ --max-count 10 -A 3

Repository: MatheMatrix/zstack

Length of output: 44


🏁 Script executed:

# Search for repository or query helper patterns in compute module
rg "Query.*Tuple|repository.*query" compute/src/main/java/org/zstack/compute/ -t java -A 3 --max-count 15

Repository: MatheMatrix/zstack

Length of output: 10417


🏁 Script executed:

# Look for alternative query patterns - checking how similar data fetching is done
rg "BackupStorage|getEntityManager.*createQuery" compute/src/main/java/org/zstack/compute/vm/ -t java -B 2 -A 2

Repository: MatheMatrix/zstack

Length of output: 50374


🏁 Script executed:

# Check if there are repository classes or query builders for BackupStorageVO
fd -t f ".*Repository.*|.*Query.*" compute/src/main/java/org/zstack/compute/ --exec basename {} \;

Repository: MatheMatrix/zstack

Length of output: 44


🏁 Script executed:

# Search for how multiple field selection queries are handled elsewhere
rg "select.*from.*where.*and.*status|name.*status" storage/src/main/java/ -t java --max-count 5 -B 1 -A 3

Repository: MatheMatrix/zstack

Length of output: 11670


避免在新增代码中直接使用 TypedQuery

第 54-55 行与第 70-71 行新增了 TypedQuery<Tuple> 的直接使用。建议改用统一的数据库查询封装方式(如仓库模式),以保持代码风格一致。

Also applies to: 70-71

🤖 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/VmDownloadIsoFlow.java` around
lines 54 - 55, The new code in VmDownloadIsoFlow creates a TypedQuery<Tuple>
directly (dbf.getEntityManager().createQuery(sql, Tuple.class) and
q.setParameter("imageUuid", imageUuid)); replace these direct TypedQuery usages
with the project's unified DB query wrapper (e.g., SimpleQuery/SQLBatch or the
DbFacade helper methods used elsewhere) so queries follow the repository/DB
facade pattern: locate the sql and imageUuid usage in VmDownloadIsoFlow and
rewrite the two query sites (the Tuple-typed query at both additions) to use the
project's standard query helper (passing the SQL and parameter map) instead of
instantiating TypedQuery directly.

Comment on lines +167 to +168
TypedQuery<Tuple> q = dbf.getEntityManager().createQuery(sql, Tuple.class);
q.setParameter("imageUuid", imageUuid);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, check if the file exists and read the relevant lines
if [ -f "compute/src/main/java/org/zstack/compute/vm/VmImageSelectBackupStorageFlow.java" ]; then
  echo "=== File exists, checking lines 160-195 for context ==="
  sed -n '160,195p' compute/src/main/java/org/zstack/compute/vm/VmImageSelectBackupStorageFlow.java
else
  echo "File not found at specified path"
  find . -name "VmImageSelectBackupStorageFlow.java" 2>/dev/null
fi

Repository: MatheMatrix/zstack

Length of output: 1719


🏁 Script executed:

# Search for Q and QueryMore usage patterns in the project
echo "=== Searching for Q usage pattern ==="
rg "new Q\(" --type java -B 2 -A 2 | head -50

echo -e "\n=== Searching for QueryMore usage pattern ==="
rg "QueryMore" --type java -B 2 -A 2 | head -50

Repository: MatheMatrix/zstack

Length of output: 3651


🏁 Script executed:

# Check for TypedQuery usage patterns to understand current practice
echo "=== Checking TypedQuery usage in codebase ==="
rg "TypedQuery" --type java | head -20

echo -e "\n=== Checking for similar query patterns in compute module ==="
rg "dbf\.getEntityManager\(\)" compute/ --type java | head -10

Repository: MatheMatrix/zstack

Length of output: 4596


🏁 Script executed:

# Check QueryMore implementation for select/projection support
echo "=== Checking QueryMore for select method ==="
rg "public.*select" core/src/main/java/org/zstack/core/db/QueryMore.java -A 3

echo -e "\n=== Checking for Tuple usage with Q/QueryMore ==="
rg "QueryMore.*select" --type java -B 2 -A 3 | head -40

echo -e "\n=== Check Q usage examples with multiple columns ==="
rg "Q\.New.*select|QueryMore.*list\|find" --type java -B 2 -A 5 | head -60

Repository: MatheMatrix/zstack

Length of output: 11052


🏁 Script executed:

# Check how to construct queries with Q/QueryMore for Tuple-like results
echo "=== Checking QueryMore source for select method signature ==="
sed -n '1,100p' core/src/main/java/org/zstack/core/db/QueryMore.java | grep -A 10 "select"

Repository: MatheMatrix/zstack

Length of output: 554


🏁 Script executed:

# Check how QueryMore.list() returns results when multiple columns are selected
echo "=== Checking QueryMore.list() method signature and return type ==="
rg "public.*list\(\)" core/src/main/java/org/zstack/core/db/QueryMore.java -A 5

echo -e "\n=== Check examples of multi-attribute selects with list/find methods ==="
rg "\.select\([^)]*,\s*[^)]*\)" --type java -B 2 -A 5 | head -80

Repository: MatheMatrix/zstack

Length of output: 9535


🏁 Script executed:

# Check if there are examples using QueryMore to select multiple attributes
echo "=== Search for QueryMore usage with 2+ select parameters ==="
grep -r "select(" compute/ --include="*.java" -A 5 | head -40

Repository: MatheMatrix/zstack

Length of output: 4845


🏁 Script executed:

# Check the QueryMore list method to understand return type
sed -n '1,500p' core/src/main/java/org/zstack/core/db/QueryMore.java | grep -A 15 "public.*List.*list()"

Repository: MatheMatrix/zstack

Length of output: 768


避免使用 TypedQuery,改用项目统一查询封装 Q/QueryMore

第 167-168 行和第 184-185 行的新增查询直接使用了 TypedQuery,违反了编码规范要求。应改为项目统一的 Q/QueryMore 查询框架,以保持一致性。

参考示例:

Q.New(BackupStorageVO.class, ImageBackupStorageRefVO.class)
    .select(BackupStorageVO_.name, BackupStorageVO_.status)
    // 添加关联条件
    .listTuple();
🤖 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/VmImageSelectBackupStorageFlow.java`
around lines 167 - 168, Replace the direct JPA TypedQuery usage (the local
variable q created with dbf.getEntityManager().createQuery and
q.setParameter("imageUuid", ...)) inside VmImageSelectBackupStorageFlow with the
project's Q/QueryMore query API; build a query starting from
Q.New(BackupStorageVO.class, ImageBackupStorageRefVO.class) (or equivalent
QueryMore) to add the join/filter on ImageBackupStorageRefVO.imageUuid, select
the same columns (or tuples) previously requested, and call listTuple() (or the
QueryMore equivalent) to fetch results—remove the TypedQuery instantiation and
parameter binding and mirror the original selection/where logic using
Q/QueryMore methods.

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.

3 participants