Skip to content

Commit f34e26d

Browse files
Add Node Weight to GetDesiredBalance (#131025)
Extends the `_internal/desired_balance` API to return the node weights. These are found within the `DesiredBalanceResponse.ClusterBalanceStats .NodeBalanceStats` object. If no node weights have been calculated, then this value defaults to null. Issue: #126579
1 parent 72bd5a0 commit f34e26d

File tree

8 files changed

+597
-62
lines changed

8 files changed

+597
-62
lines changed

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cluster.desired_balance/10_basic.yml

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22
setup:
33
- requires:
44
cluster_features: ["gte_v8.6.0"]
5-
reason: "API added in in 8.6.0"
5+
reason: "API added in 8.6.0"
66

77
---
88
"Test get empty desired balance":
9-
109
- do:
1110
_internal.get_desired_balance: { }
1211

@@ -63,7 +62,7 @@ setup:
6362

6463
- requires:
6564
cluster_features: ["gte_v8.7.0"]
66-
reason: "cluster_balance_stats added in in 8.7.0"
65+
reason: "cluster_balance_stats added in 8.7.0"
6766

6867
- do:
6968
cluster.state: {}
@@ -111,7 +110,7 @@ setup:
111110

112111
- requires:
113112
cluster_features: [gte_v8.8.0]
114-
reason: "cluster_info added in in 8.8.0"
113+
reason: "cluster_info added in 8.8.0"
115114

116115
- do:
117116
_internal.get_desired_balance: { }
@@ -123,7 +122,7 @@ setup:
123122

124123
- requires:
125124
cluster_features: ["gte_v8.8.0"]
126-
reason: "node_id and roles added in in 8.8.0"
125+
reason: "node_id and roles added in 8.8.0"
127126

128127
- do:
129128
cluster.state: {}
@@ -142,7 +141,7 @@ setup:
142141

143142
- requires:
144143
cluster_features: ["gte_v8.8.0"]
145-
reason: "tier_preference added in in 8.8.0"
144+
reason: "tier_preference added in 8.8.0"
146145

147146
- do:
148147
indices.create:
@@ -167,7 +166,7 @@ setup:
167166

168167
- requires:
169168
cluster_features: ["gte_v8.8.0"]
170-
reason: "computed_shard_movements added in in 8.8.0"
169+
reason: "computed_shard_movements added in 8.8.0"
171170

172171
- do:
173172
_internal.get_desired_balance: { }
@@ -179,7 +178,7 @@ setup:
179178

180179
- requires:
181180
cluster_features: ["gte_v8.8.0"]
182-
reason: "reset API added in in 8.8.0"
181+
reason: "reset API added in 8.8.0"
183182
test_runner_features: [ capabilities ]
184183
capabilities:
185184
- method: DELETE
@@ -194,7 +193,7 @@ setup:
194193

195194
- requires:
196195
cluster_features: ["gte_v8.12.0"]
197-
reason: "undesired_shard_allocation_count added in in 8.12.0"
196+
reason: "undesired_shard_allocation_count added in 8.12.0"
198197

199198
- do:
200199
indices.create:
@@ -232,7 +231,7 @@ setup:
232231

233232
- requires:
234233
cluster_features: [ "gte_v8.12.0" ]
235-
reason: "undesired_shard_allocation_count added in in 8.12.0"
234+
reason: "undesired_shard_allocation_count added in 8.12.0"
236235

237236
- do:
238237
_internal.get_desired_balance: { }
@@ -241,3 +240,37 @@ setup:
241240
- gte: { 'stats.total_allocations' : 0 }
242241
- gte: { 'stats.undesired_allocations' : 0 }
243242
- gte: { 'stats.undesired_allocations_ratio' : 0.0 }
243+
244+
---
245+
"Test node_weights":
246+
247+
- requires:
248+
capabilities:
249+
- method: GET
250+
path: /_internal/desired_balance
251+
capabilities: [ desired_balance_node_weights_in_response ]
252+
test_runner_features: [ capabilities ]
253+
reason: "Node weights were added in version 9.2.0"
254+
255+
- do:
256+
indices.create:
257+
index: test
258+
body:
259+
settings:
260+
number_of_shards: 1
261+
number_of_replicas: 0
262+
263+
- do:
264+
cluster.health:
265+
index: test
266+
wait_for_status: green
267+
268+
- do:
269+
cluster.state: { }
270+
- set: { nodes._arbitrary_key_: node_id }
271+
- set: { nodes.$node_id.name: node_name }
272+
273+
- do:
274+
_internal.get_desired_balance: { }
275+
276+
- exists: cluster_balance_stats.nodes.$node_name.node_weight

server/src/main/java/org/elasticsearch/TransportVersions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ static TransportVersion def(int id) {
351351
public static final TransportVersion SHARD_WRITE_LOAD_IN_CLUSTER_INFO = def(9_126_0_00);
352352
public static final TransportVersion ESQL_SAMPLE_OPERATOR_STATUS = def(9_127_0_00);
353353
public static final TransportVersion ESQL_TOPN_TIMINGS = def(9_128_0_00);
354+
public static final TransportVersion NODE_WEIGHTS_ADDED_TO_NODE_BALANCE_STATS = def(9_129_0_00);
354355

355356
/*
356357
* STOP! READ THIS FIRST! No, really,

server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/ClusterBalanceStats.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.HashMap;
3131
import java.util.List;
3232
import java.util.Map;
33+
import java.util.Optional;
3334
import java.util.function.ToDoubleFunction;
3435

3536
public record ClusterBalanceStats(
@@ -213,7 +214,8 @@ public record NodeBalanceStats(
213214
int undesiredShardAllocations,
214215
double forecastWriteLoad,
215216
long forecastShardSize,
216-
long actualShardSize
217+
long actualShardSize,
218+
Double nodeWeight
217219
) implements Writeable, ToXContentObject {
218220

219221
private static final String UNKNOWN_NODE_ID = "UNKNOWN";
@@ -241,14 +243,20 @@ private static NodeBalanceStats createFrom(
241243
}
242244
}
243245

246+
assert desiredBalance != null;
247+
Double nodeWeight = Optional.ofNullable(desiredBalance.weightsPerNode().get(routingNode.node()))
248+
.map(DesiredBalanceMetrics.NodeWeightStats::nodeWeight)
249+
.orElse(null);
250+
244251
return new NodeBalanceStats(
245252
routingNode.nodeId(),
246253
routingNode.node().getRoles().stream().map(DiscoveryNodeRole::roleName).toList(),
247254
routingNode.size(),
248255
undesired,
249256
forecastWriteLoad,
250257
forecastShardSize,
251-
actualShardSize
258+
actualShardSize,
259+
nodeWeight
252260
);
253261
}
254262

@@ -269,7 +277,10 @@ public static NodeBalanceStats readFrom(StreamInput in) throws IOException {
269277
in.getTransportVersion().onOrAfter(TransportVersions.V_8_12_0) ? in.readVInt() : -1,
270278
in.readDouble(),
271279
in.readLong(),
272-
in.readLong()
280+
in.readLong(),
281+
in.getTransportVersion().onOrAfter(TransportVersions.NODE_WEIGHTS_ADDED_TO_NODE_BALANCE_STATS)
282+
? in.readOptionalDouble()
283+
: null
273284
);
274285
}
275286

@@ -286,6 +297,9 @@ public void writeTo(StreamOutput out) throws IOException {
286297
out.writeDouble(forecastWriteLoad);
287298
out.writeLong(forecastShardSize);
288299
out.writeLong(actualShardSize);
300+
if (out.getTransportVersion().onOrAfter(TransportVersions.NODE_WEIGHTS_ADDED_TO_NODE_BALANCE_STATS)) {
301+
out.writeOptionalDouble(nodeWeight);
302+
}
289303
}
290304

291305
@Override
@@ -294,13 +308,16 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
294308
if (UNKNOWN_NODE_ID.equals(nodeId) == false) {
295309
builder.field("node_id", nodeId);
296310
}
297-
return builder.field("roles", roles)
311+
builder.field("roles", roles)
298312
.field("shard_count", shards)
299313
.field("undesired_shard_allocation_count", undesiredShardAllocations)
300314
.field("forecast_write_load", forecastWriteLoad)
301315
.humanReadableField("forecast_disk_usage_bytes", "forecast_disk_usage", ByteSizeValue.ofBytes(forecastShardSize))
302-
.humanReadableField("actual_disk_usage_bytes", "actual_disk_usage", ByteSizeValue.ofBytes(actualShardSize))
303-
.endObject();
316+
.humanReadableField("actual_disk_usage_bytes", "actual_disk_usage", ByteSizeValue.ofBytes(actualShardSize));
317+
if (nodeWeight != null) {
318+
builder.field("node_weight", nodeWeight);
319+
}
320+
return builder.endObject();
304321
}
305322
}
306323
}

server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetDesiredBalanceAction.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import java.io.IOException;
2323
import java.util.List;
24+
import java.util.Set;
2425

2526
@ServerlessScope(Scope.INTERNAL)
2627
public class RestGetDesiredBalanceAction extends BaseRestHandler {
@@ -44,4 +45,9 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli
4445
new RestRefCountedChunkedToXContentListener<>(restChannel)
4546
);
4647
}
48+
49+
@Override
50+
public Set<String> supportedCapabilities() {
51+
return Set.of("desired_balance_node_weights_in_response");
52+
}
4753
}

server/src/test/java/org/elasticsearch/action/admin/cluster/allocation/DesiredBalanceResponseTests.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ private ClusterBalanceStats.NodeBalanceStats randomNodeBalanceStats() {
9191
randomNonNegativeInt(),
9292
randomDouble(),
9393
randomNonNegativeLong(),
94-
randomNonNegativeLong()
94+
randomNonNegativeLong(),
95+
randomDouble()
9596
);
9697
}
9798

@@ -283,7 +284,8 @@ public void testToXContent() throws IOException {
283284
"undesired_shard_allocation_count",
284285
"forecast_write_load",
285286
"forecast_disk_usage_bytes",
286-
"actual_disk_usage_bytes"
287+
"actual_disk_usage_bytes",
288+
"node_weight"
287289
)
288290
);
289291
assertEquals(nodesStats.get("node_id"), entry.getValue().nodeId());
@@ -293,6 +295,7 @@ public void testToXContent() throws IOException {
293295
assertEquals(nodesStats.get("forecast_write_load"), entry.getValue().forecastWriteLoad());
294296
assertEquals(nodesStats.get("forecast_disk_usage_bytes"), entry.getValue().forecastShardSize());
295297
assertEquals(nodesStats.get("actual_disk_usage_bytes"), entry.getValue().actualShardSize());
298+
assertEquals(nodesStats.get("node_weight"), entry.getValue().nodeWeight());
296299
}
297300

298301
// routing table

0 commit comments

Comments
 (0)