-
Notifications
You must be signed in to change notification settings - Fork 0
<fix>[vm]: improve error messages for backup storage selection failures #3396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 5.5.12
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| import org.zstack.header.image.ImageBackupStorageRefInventory; | ||
| import org.zstack.header.image.ImageConstant.ImageMediaType; | ||
| import org.zstack.header.image.ImageStatus; | ||
| import org.zstack.header.storage.backup.BackupStorageStatus; | ||
| import org.zstack.header.storage.primary.*; | ||
| import org.zstack.header.vm.VmInstanceConstant; | ||
| import org.zstack.header.vm.VmInstanceConstant.VmOperation; | ||
|
|
@@ -22,11 +23,14 @@ | |
| import org.zstack.utils.DebugUtils; | ||
| import org.zstack.utils.function.Function; | ||
|
|
||
| import javax.persistence.Tuple; | ||
| import javax.persistence.TypedQuery; | ||
| import java.util.Collections; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import static org.zstack.core.Platform.operr; | ||
| import static org.zstack.core.progress.ProgressReportService.taskProgress; | ||
|
|
@@ -76,17 +80,27 @@ private String findBackupStorage(VmInstanceSpec spec, String imageUuid) { | |
| } | ||
| } | ||
|
|
||
| String imageName = spec.getImageSpec().getInventory().getName(); | ||
| String imageBsInfo = getImageBackupStorageInfo(imageUuid); | ||
| if (spec.getVmInventory().getZoneUuid() != null) { | ||
| throw new OperationFailureException(operr(ORG_ZSTACK_COMPUTE_VM_10085, "cannot find the image[uuid:%s] in any connected backup storage attached to the zone[uuid:%s]. check below:\n" + | ||
| "1. if the backup storage is attached to the zone where the VM[name: %s, uuid:%s] is in\n" + | ||
| "2. if the backup storage is in connected status, if not, try reconnecting it", | ||
| imageUuid, spec.getVmInventory().getZoneUuid(), spec.getVmInventory().getName(), spec.getVmInventory().getUuid()) | ||
| String zoneUuid = spec.getVmInventory().getZoneUuid(); | ||
| String zoneBsInfo = getZoneBackupStorageInfo(zoneUuid); | ||
| throw new OperationFailureException(operr(ORG_ZSTACK_COMPUTE_VM_10085, | ||
| "cannot find the image[name:%s, uuid:%s] in any connected backup storage" + | ||
| " attached to the zone[uuid:%s]." + | ||
| "\nimage is on backup storage: %s" + | ||
| "\nzone attached backup storage: %s" + | ||
| "\nsuggestion: attach the image's backup storage to the zone," + | ||
| " or sync the image to an attached and connected backup storage.", | ||
| imageName, imageUuid, zoneUuid, imageBsInfo, zoneBsInfo) | ||
| ); | ||
| } else { | ||
| throw new OperationFailureException(operr(ORG_ZSTACK_COMPUTE_VM_10086, "cannot find the image[uuid:%s] in any connected backup storage. check below:\n" + | ||
| "1. if the backup storage is attached to the zone where the VM[name: %s, uuid:%s] is in\n" + | ||
| "2. if the backup storage is in connected status, if not, try reconnecting it", | ||
| imageUuid, spec.getVmInventory().getName(), spec.getVmInventory().getUuid()) | ||
| throw new OperationFailureException(operr(ORG_ZSTACK_COMPUTE_VM_10086, | ||
| "cannot find the image[name:%s, uuid:%s] in any connected backup storage." + | ||
| "\nimage is on backup storage: %s" + | ||
| "\nsuggestion: ensure the backup storage is connected," + | ||
| " or sync the image to a connected backup storage.", | ||
| imageName, imageUuid, imageBsInfo) | ||
| ); | ||
| } | ||
| } | ||
|
|
@@ -126,13 +140,58 @@ private String findIsoBsUuidInTheZone(final String isoImageUuid, final String zo | |
| q.setMaxResults(1); | ||
| List<String> ret = q.getResultList(); | ||
| if (ret.isEmpty()) { | ||
| throw new OperationFailureException(operr(ORG_ZSTACK_COMPUTE_VM_10087, "no backup storage attached to the zone[uuid:%s] contains the ISO[uuid:%s]", | ||
| zoneUuid, isoImageUuid)); | ||
| String isoName = Optional.ofNullable((String) Q.New(org.zstack.header.image.ImageVO.class) | ||
| .eq(org.zstack.header.image.ImageVO_.uuid, isoImageUuid) | ||
| .select(org.zstack.header.image.ImageVO_.name) | ||
| .findValue()).orElse(isoImageUuid); | ||
| String isoBsInfo = getImageBackupStorageInfo(isoImageUuid); | ||
| String zoneBsInfo = getZoneBackupStorageInfo(zoneUuid); | ||
| throw new OperationFailureException(operr(ORG_ZSTACK_COMPUTE_VM_10087, | ||
| "no backup storage attached to the zone[uuid:%s] contains the ISO[name:%s, uuid:%s]." + | ||
| "\nISO is on backup storage: %s" + | ||
| "\nzone attached backup storage: %s" + | ||
| "\nsuggestion: attach the ISO's backup storage to the zone," + | ||
| " or sync the ISO to an attached backup storage.", | ||
| zoneUuid, isoName, isoImageUuid, isoBsInfo, zoneBsInfo)); | ||
| } | ||
|
|
||
| return ret.get(0); | ||
| } | ||
|
|
||
| @Transactional(readOnly = true) | ||
| private String getImageBackupStorageInfo(String imageUuid) { | ||
| String sql = "select bs.name, bs.status" + | ||
| " from BackupStorageVO bs, ImageBackupStorageRefVO ref" + | ||
| " where bs.uuid = ref.backupStorageUuid" + | ||
| " and ref.imageUuid = :imageUuid"; | ||
| TypedQuery<Tuple> q = dbf.getEntityManager().createQuery(sql, Tuple.class); | ||
| q.setParameter("imageUuid", imageUuid); | ||
|
Comment on lines
+167
to
+168
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 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
fiRepository: 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 -50Repository: 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 -10Repository: 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 -60Repository: 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 -80Repository: 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 -40Repository: 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 避免使用 第 167-168 行和第 184-185 行的新增查询直接使用了 参考示例: 🤖 Prompt for AI Agents |
||
| List<Tuple> tuples = q.getResultList(); | ||
| if (tuples.isEmpty()) { | ||
| return "none"; | ||
| } | ||
| return tuples.stream() | ||
| .map(t -> String.format("%s(%s)", t.get(0, String.class), t.get(1, BackupStorageStatus.class))) | ||
| .collect(Collectors.joining(", ", "[", "]")); | ||
| } | ||
|
|
||
| @Transactional(readOnly = true) | ||
| private String getZoneBackupStorageInfo(String zoneUuid) { | ||
| String sql = "select bs.name, bs.status" + | ||
| " from BackupStorageVO bs, BackupStorageZoneRefVO ref" + | ||
| " where bs.uuid = ref.backupStorageUuid" + | ||
| " and ref.zoneUuid = :zoneUuid"; | ||
| TypedQuery<Tuple> q = dbf.getEntityManager().createQuery(sql, Tuple.class); | ||
| q.setParameter("zoneUuid", zoneUuid); | ||
| List<Tuple> tuples = q.getResultList(); | ||
| if (tuples.isEmpty()) { | ||
| return "none"; | ||
| } | ||
| return tuples.stream() | ||
| .map(t -> String.format("%s(%s)", t.get(0, String.class), t.get(1, BackupStorageStatus.class))) | ||
| .collect(Collectors.joining(", ", "[", "]")); | ||
| } | ||
|
|
||
| @Override | ||
| public void run(FlowTrigger trigger, Map data) { | ||
| VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString()); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: MatheMatrix/zstack
Length of output: 134
🏁 Script executed:
Repository: MatheMatrix/zstack
Length of output: 5244
🏁 Script executed:
Repository: MatheMatrix/zstack
Length of output: 50375
🏁 Script executed:
Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
Repository: MatheMatrix/zstack
Length of output: 10417
🏁 Script executed:
Repository: MatheMatrix/zstack
Length of output: 50374
🏁 Script executed:
Repository: MatheMatrix/zstack
Length of output: 44
🏁 Script executed:
Repository: MatheMatrix/zstack
Length of output: 11670
避免在新增代码中直接使用
TypedQuery。第 54-55 行与第 70-71 行新增了
TypedQuery<Tuple>的直接使用。建议改用统一的数据库查询封装方式(如仓库模式),以保持代码风格一致。Also applies to: 70-71
🤖 Prompt for AI Agents