Skip to content

Commit 78389bb

Browse files
committed
<fix>[compute]: handle empty string dstHostUuid in host allocator
When performing "change host and primary storage" without specifying a target host, the frontend sends dstHostUuid="" (empty string) instead of null. 1. Why is this change necessary? DesignatedHostAllocatorFlow only checked hostUuid for null, not empty string. Empty string caused SQL to generate "h.uuid = ''" which matched no hosts, making all storage migrations without a specified host fail. 2. How does it address the problem? Normalize empty string hostUuid, zoneUuid, and clusterUuids to null in DesignatedHostAllocatorFlow.allocate() before any filtering logic. This treats empty string as "not specified", which is the correct semantic. Also fix a pre-existing NPE in the error-message path where clusterUuids.isEmpty() was called without null check. 3. Are there any side effects? None. A valid UUID is never an empty string. All existing callers passing null or valid UUIDs are unaffected. # Summary of changes (by module): - compute: normalize empty strings to null for hostUuid, zoneUuid, and clusterUuids in DesignatedHostAllocatorFlow.allocate(); fix NPE in error-message path Related: ZSTAC-83733 Change-Id: Ib669b3f7087e9fcda7f5dd5aa6362c5e653d803d
1 parent 226b20b commit 78389bb

1 file changed

Lines changed: 21 additions & 6 deletions

File tree

compute/src/main/java/org/zstack/compute/allocator/DesignatedHostAllocatorFlow.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.zstack.compute.allocator;
22

33
import org.apache.commons.collections.CollectionUtils;
4+
import org.apache.commons.lang.StringUtils;
45
import org.springframework.beans.factory.annotation.Autowire;
56
import org.springframework.beans.factory.annotation.Autowired;
67
import org.springframework.beans.factory.annotation.Configurable;
@@ -81,30 +82,44 @@ public void allocate() {
8182
List<String> clusterUuids = (List<String>) spec.getExtraData().get(HostAllocatorConstant.LocationSelector.cluster);
8283
String hostUuid = (String) spec.getExtraData().get(HostAllocatorConstant.LocationSelector.host);
8384

84-
if (zoneUuid == null && CollectionUtils.isEmpty(clusterUuids) && hostUuid == null && spec.getHypervisorType() == null) {
85+
String hypervisorType = spec.getHypervisorType();
86+
87+
// normalize empty strings to null — treat empty string as "not specified"
88+
zoneUuid = StringUtils.isEmpty(zoneUuid) ? null : zoneUuid;
89+
hostUuid = StringUtils.isEmpty(hostUuid) ? null : hostUuid;
90+
hypervisorType = StringUtils.isEmpty(hypervisorType) ? null : hypervisorType;
91+
if (!CollectionUtils.isEmpty(clusterUuids)) {
92+
clusterUuids = new ArrayList<>(clusterUuids);
93+
clusterUuids.removeIf(s -> s == null || s.isEmpty());
94+
if (clusterUuids.isEmpty()) {
95+
clusterUuids = null;
96+
}
97+
}
98+
99+
if (zoneUuid == null && CollectionUtils.isEmpty(clusterUuids) && hostUuid == null && hypervisorType == null) {
85100
next(candidates);
86101
return;
87102
}
88103

89104
if (amITheFirstFlow()) {
90-
candidates = allocate(zoneUuid, clusterUuids, hostUuid, spec.getHypervisorType());
105+
candidates = allocate(zoneUuid, clusterUuids, hostUuid, hypervisorType);
91106
} else {
92-
candidates = allocate(candidates, zoneUuid, clusterUuids, hostUuid, spec.getHypervisorType());
107+
candidates = allocate(candidates, zoneUuid, clusterUuids, hostUuid, hypervisorType);
93108
}
94109

95110
if (candidates.isEmpty()) {
96111
StringBuilder args = new StringBuilder();
97112
if (zoneUuid != null) {
98113
args.append(String.format("zoneUuid=%s", zoneUuid)).append(" ");
99114
}
100-
if (!clusterUuids.isEmpty()) {
115+
if (!CollectionUtils.isEmpty(clusterUuids)) {
101116
args.append(String.format("clusterUuid in %s", clusterUuids)).append(" ");
102117
}
103118
if (hostUuid != null) {
104119
args.append(String.format("hostUuid=%s", hostUuid)).append(" ");
105120
}
106-
if (spec.getHypervisorType() != null) {
107-
args.append(String.format("hypervisorType=%s", spec.getHypervisorType())).append(" ");
121+
if (hypervisorType != null) {
122+
args.append(String.format("hypervisorType=%s", hypervisorType)).append(" ");
108123
}
109124
fail(Platform.operr(ORG_ZSTACK_COMPUTE_ALLOCATOR_10036, "No host with %s found", args));
110125
} else {

0 commit comments

Comments
 (0)