Skip to content

Commit 68f7849

Browse files
authored
Merge branch 'main' into update.lucene.9.12.1
Signed-off-by: Andriy Redko <[email protected]>
2 parents bbc1381 + ef44e86 commit 68f7849

File tree

12 files changed

+103
-18
lines changed

12 files changed

+103
-18
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
2323
- Add stats for remote publication failure and move download failure stats to remote methods([#16682](https://github.com/opensearch-project/OpenSearch/pull/16682/))
2424
- Added a precaution to handle extreme date values during sorting to prevent `arithmetic_exception: long overflow` ([#16812](https://github.com/opensearch-project/OpenSearch/pull/16812)).
2525
- Add search replica stats to segment replication stats API ([#16678](https://github.com/opensearch-project/OpenSearch/pull/16678))
26+
- Introduce a setting to disable download of full cluster state from remote on term mismatch([#16798](https://github.com/opensearch-project/OpenSearch/pull/16798/))
2627

2728
### Dependencies
2829
- Bump `com.google.cloud:google-cloud-core-http` from 2.23.0 to 2.47.0 ([#16504](https://github.com/opensearch-project/OpenSearch/pull/16504))
@@ -44,6 +45,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
4445
- Bump `ch.qos.logback:logback-classic` from 1.2.13 to 1.5.12 ([#16716](https://github.com/opensearch-project/OpenSearch/pull/16716))
4546
- Bump `com.azure:azure-identity` from 1.13.2 to 1.14.2 ([#16778](https://github.com/opensearch-project/OpenSearch/pull/16778))
4647
- Bump Apache Lucene from 9.12.0 to 9.12.1 ([#16846](https://github.com/opensearch-project/OpenSearch/pull/16846))
48+
- Bump `com.gradle.develocity` from 3.18.2 to 3.19 ([#16855](https://github.com/opensearch-project/OpenSearch/pull/16855))
4749

4850
### Changed
4951
- Indexed IP field supports `terms_query` with more than 1025 IP masks [#16391](https://github.com/opensearch-project/OpenSearch/pull/16391)
@@ -69,6 +71,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6971
- Ensure consistency of system flag on IndexMetadata after diff is applied ([#16644](https://github.com/opensearch-project/OpenSearch/pull/16644))
7072
- Skip remote-repositories validations for node-joins when RepositoriesService is not in sync with cluster-state ([#16763](https://github.com/opensearch-project/OpenSearch/pull/16763))
7173
- Fix _list/shards API failing when closed indices are present ([#16606](https://github.com/opensearch-project/OpenSearch/pull/16606))
74+
- Fix remote shards balance ([#15335](https://github.com/opensearch-project/OpenSearch/pull/15335))
7275

7376
### Security
7477

server/src/main/java/org/opensearch/action/support/clustermanager/term/TransportGetTermVersionAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ private GetTermVersionResponse buildResponse(GetTermVersionRequest request, Clus
9898
ClusterStateTermVersion termVersion = new ClusterStateTermVersion(state);
9999
if (discovery instanceof Coordinator) {
100100
Coordinator coordinator = (Coordinator) discovery;
101-
if (coordinator.isRemotePublicationEnabled()) {
101+
if (coordinator.canDownloadFullStateFromRemote()) {
102102
return new GetTermVersionResponse(termVersion, coordinator.isRemotePublicationEnabled());
103103
}
104104
}

server/src/main/java/org/opensearch/cluster/coordination/Coordinator.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,4 +1906,12 @@ public boolean isRemotePublicationEnabled() {
19061906
}
19071907
return false;
19081908
}
1909+
1910+
public boolean canDownloadFullStateFromRemote() {
1911+
if (remoteClusterStateService != null) {
1912+
return remoteClusterStateService.isRemotePublicationEnabled() && remoteClusterStateService.canDownloadFromRemoteForReadAPI();
1913+
}
1914+
return false;
1915+
}
1916+
19091917
}

server/src/main/java/org/opensearch/cluster/routing/allocation/allocator/RemoteShardsBalancer.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,17 @@ void balance() {
247247
final Map<String, Integer> nodePrimaryShardCount = calculateNodePrimaryShardCount(remoteRoutingNodes);
248248
int totalPrimaryShardCount = nodePrimaryShardCount.values().stream().reduce(0, Integer::sum);
249249

250-
totalPrimaryShardCount += routingNodes.unassigned().getNumPrimaries();
251-
int avgPrimaryPerNode = (totalPrimaryShardCount + routingNodes.size() - 1) / routingNodes.size();
250+
int unassignedRemotePrimaryShardCount = 0;
251+
for (ShardRouting shard : routingNodes.unassigned()) {
252+
if (RoutingPool.REMOTE_CAPABLE.equals(RoutingPool.getShardPool(shard, allocation)) && shard.primary()) {
253+
unassignedRemotePrimaryShardCount++;
254+
}
255+
}
256+
totalPrimaryShardCount += unassignedRemotePrimaryShardCount;
257+
final int avgPrimaryPerNode = (totalPrimaryShardCount + remoteRoutingNodes.size() - 1) / remoteRoutingNodes.size();
252258

253-
ArrayDeque<RoutingNode> sourceNodes = new ArrayDeque<>();
254-
ArrayDeque<RoutingNode> targetNodes = new ArrayDeque<>();
259+
final ArrayDeque<RoutingNode> sourceNodes = new ArrayDeque<>();
260+
final ArrayDeque<RoutingNode> targetNodes = new ArrayDeque<>();
255261
for (RoutingNode node : remoteRoutingNodes) {
256262
if (nodePrimaryShardCount.get(node.nodeId()) > avgPrimaryPerNode) {
257263
sourceNodes.add(node);

server/src/main/java/org/opensearch/cluster/service/ClusterApplierService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,13 @@ public ClusterState state() {
233233
return clusterState;
234234
}
235235

236+
/**
237+
* Returns true if the appliedClusterState is not null
238+
*/
239+
public boolean isStateInitialised() {
240+
return this.state.get() != null;
241+
}
242+
236243
/**
237244
* Returns true if the appliedClusterState is not null
238245
*/

server/src/main/java/org/opensearch/cluster/service/ClusterService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,13 @@ public ClusterState state() {
183183
return clusterApplierService.state();
184184
}
185185

186+
/**
187+
* Returns true if the state in appliedClusterState is not null
188+
*/
189+
public boolean isStateInitialised() {
190+
return clusterApplierService.isStateInitialised();
191+
}
192+
186193
/**
187194
* The state that is persisted to store but may not be applied to cluster.
188195
* @return ClusterState

server/src/main/java/org/opensearch/common/settings/ClusterSettings.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,8 @@ public void apply(Settings value, Settings current, Settings previous) {
738738
RemoteClusterStateCleanupManager.REMOTE_CLUSTER_STATE_CLEANUP_INTERVAL_SETTING,
739739
RemoteClusterStateService.REMOTE_CLUSTER_STATE_ENABLED_SETTING,
740740
RemoteClusterStateService.REMOTE_PUBLICATION_SETTING,
741+
RemoteClusterStateService.REMOTE_STATE_DOWNLOAD_TO_SERVE_READ_API,
742+
741743
INDEX_METADATA_UPLOAD_TIMEOUT_SETTING,
742744
GLOBAL_METADATA_UPLOAD_TIMEOUT_SETTING,
743745
METADATA_MANIFEST_UPLOAD_TIMEOUT_SETTING,

server/src/main/java/org/opensearch/gateway/remote/RemoteClusterStateService.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ public class RemoteClusterStateService implements Closeable {
129129
* Gates the functionality of remote publication.
130130
*/
131131
public static final String REMOTE_PUBLICATION_SETTING_KEY = "cluster.remote_store.publication.enabled";
132+
public static final String REMOTE_STATE_DOWNLOAD_TO_SERVE_READ_API_KEY = "cluster.remote_state.download.serve_read_api.enabled";
132133

133134
public static final Setting<Boolean> REMOTE_PUBLICATION_SETTING = Setting.boolSetting(
134135
REMOTE_PUBLICATION_SETTING_KEY,
@@ -137,6 +138,13 @@ public class RemoteClusterStateService implements Closeable {
137138
Property.Dynamic
138139
);
139140

141+
public static final Setting<Boolean> REMOTE_STATE_DOWNLOAD_TO_SERVE_READ_API = Setting.boolSetting(
142+
REMOTE_STATE_DOWNLOAD_TO_SERVE_READ_API_KEY,
143+
true,
144+
Property.NodeScope,
145+
Property.Dynamic
146+
);
147+
140148
/**
141149
* Used to specify if cluster state metadata should be published to remote store
142150
*/
@@ -235,6 +243,9 @@ public static RemoteClusterStateValidationMode parseString(String mode) {
235243
+ "indices, coordination metadata updated : [{}], settings metadata updated : [{}], templates metadata "
236244
+ "updated : [{}], custom metadata updated : [{}], indices routing updated : [{}]";
237245
private volatile AtomicBoolean isPublicationEnabled;
246+
247+
private volatile AtomicBoolean downloadFromRemoteForReadAPI;
248+
238249
private final String remotePathPrefix;
239250

240251
private final RemoteClusterStateCache remoteClusterStateCache;
@@ -281,6 +292,8 @@ public RemoteClusterStateService(
281292
&& RemoteStoreNodeAttribute.isRemoteRoutingTableConfigured(settings)
282293
);
283294
clusterSettings.addSettingsUpdateConsumer(REMOTE_PUBLICATION_SETTING, this::setRemotePublicationSetting);
295+
this.downloadFromRemoteForReadAPI = new AtomicBoolean(clusterSettings.get(REMOTE_STATE_DOWNLOAD_TO_SERVE_READ_API));
296+
clusterSettings.addSettingsUpdateConsumer(REMOTE_STATE_DOWNLOAD_TO_SERVE_READ_API, this::setRemoteDownloadForReadAPISetting);
284297
this.remotePathPrefix = CLUSTER_REMOTE_STORE_STATE_PATH_PREFIX.get(settings);
285298
this.remoteRoutingTableService = RemoteRoutingTableServiceFactory.getService(
286299
repositoriesService,
@@ -1124,6 +1137,14 @@ private void setRemotePublicationSetting(boolean remotePublicationSetting) {
11241137
}
11251138
}
11261139

1140+
private void setRemoteDownloadForReadAPISetting(boolean remoteDownloadForReadAPISetting) {
1141+
this.downloadFromRemoteForReadAPI.set(remoteDownloadForReadAPISetting);
1142+
}
1143+
1144+
public boolean canDownloadFromRemoteForReadAPI() {
1145+
return this.downloadFromRemoteForReadAPI.get();
1146+
}
1147+
11271148
// Package private for unit test
11281149
RemoteRoutingTableService getRemoteRoutingTableService() {
11291150
return this.remoteRoutingTableService;

server/src/main/java/org/opensearch/repositories/blobstore/BlobStoreRepository.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2994,7 +2994,12 @@ public String startVerification() {
29942994
*/
29952995
private BlobContainer testContainer(String seed) {
29962996
BlobPath testBlobPath;
2997-
if (prefixModeVerification == true) {
2997+
2998+
if (prefixModeVerification == true
2999+
&& (clusterService.isStateInitialised() == false
3000+
|| clusterService.state().nodes().getMinNodeVersion().onOrAfter(Version.V_2_17_0))) {
3001+
// During the remote store node bootstrap, the cluster state is not initialised
3002+
// Otherwise, the cluster state is initialised and available with the min node version information
29983003
PathInput pathInput = PathInput.builder().basePath(basePath()).indexUUID(seed).build();
29993004
testBlobPath = PathType.HASHED_PREFIX.path(pathInput, FNV_1A_COMPOSITE_1);
30003005
} else {

server/src/test/java/org/opensearch/cluster/routing/allocation/RemoteShardsBalancerBaseTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ public AllocationService createRemoteCapableAllocationService() {
194194
}
195195

196196
public AllocationService createRemoteCapableAllocationService(String excludeNodes) {
197-
Settings settings = Settings.builder().put("cluster.routing.allocation.exclude.node_id", excludeNodes).build();
197+
Settings settings = Settings.builder().put("cluster.routing.allocation.exclude._id", excludeNodes).build();
198198
return new MockAllocationService(
199199
randomAllocationDeciders(settings, EMPTY_CLUSTER_SETTINGS, random()),
200200
new TestGatewayAllocator(),

server/src/test/java/org/opensearch/cluster/routing/allocation/RemoteShardsRebalanceShardsTests.java

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,51 @@ public class RemoteShardsRebalanceShardsTests extends RemoteShardsBalancerBaseTe
2525
* Post rebalance primaries should be balanced across all the nodes.
2626
*/
2727
public void testShardAllocationAndRebalance() {
28-
int localOnlyNodes = 20;
29-
int remoteCapableNodes = 40;
30-
int localIndices = 40;
31-
int remoteIndices = 80;
28+
final int localOnlyNodes = 20;
29+
final int remoteCapableNodes = 40;
30+
final int halfRemoteCapableNodes = remoteCapableNodes / 2;
31+
final int localIndices = 40;
32+
final int remoteIndices = 80;
3233
ClusterState clusterState = createInitialCluster(localOnlyNodes, remoteCapableNodes, localIndices, remoteIndices);
33-
AllocationService service = this.createRemoteCapableAllocationService();
34+
final StringBuilder excludeNodes = new StringBuilder();
35+
for (int i = 0; i < halfRemoteCapableNodes; i++) {
36+
excludeNodes.append(getNodeId(i, true));
37+
if (i != (remoteCapableNodes / 2 - 1)) {
38+
excludeNodes.append(", ");
39+
}
40+
}
41+
AllocationService service = this.createRemoteCapableAllocationService(excludeNodes.toString());
3442
clusterState = allocateShardsAndBalance(clusterState, service);
3543
RoutingNodes routingNodes = clusterState.getRoutingNodes();
3644
RoutingAllocation allocation = getRoutingAllocation(clusterState, routingNodes);
3745

38-
final Map<String, Integer> nodePrimariesCounter = getShardCounterPerNodeForRemoteCapablePool(clusterState, allocation, true);
39-
final Map<String, Integer> nodeReplicaCounter = getShardCounterPerNodeForRemoteCapablePool(clusterState, allocation, false);
46+
Map<String, Integer> nodePrimariesCounter = getShardCounterPerNodeForRemoteCapablePool(clusterState, allocation, true);
47+
Map<String, Integer> nodeReplicaCounter = getShardCounterPerNodeForRemoteCapablePool(clusterState, allocation, false);
4048
int avgPrimariesPerNode = getTotalShardCountAcrossNodes(nodePrimariesCounter) / remoteCapableNodes;
4149

42-
// Primary and replica are balanced post first reroute
50+
// Primary and replica are balanced after first allocating unassigned
51+
for (RoutingNode node : routingNodes) {
52+
if (RoutingPool.REMOTE_CAPABLE.equals(RoutingPool.getNodePool(node))) {
53+
if (Integer.parseInt(node.nodeId().split("-")[4]) < halfRemoteCapableNodes) {
54+
assertEquals(0, (int) nodePrimariesCounter.getOrDefault(node.nodeId(), 0));
55+
} else {
56+
assertEquals(avgPrimariesPerNode * 2, (int) nodePrimariesCounter.get(node.nodeId()));
57+
}
58+
assertTrue(nodeReplicaCounter.getOrDefault(node.nodeId(), 0) >= 0);
59+
}
60+
}
61+
62+
// Remove exclude constraint and rebalance
63+
service = this.createRemoteCapableAllocationService();
64+
clusterState = allocateShardsAndBalance(clusterState, service);
65+
routingNodes = clusterState.getRoutingNodes();
66+
allocation = getRoutingAllocation(clusterState, routingNodes);
67+
nodePrimariesCounter = getShardCounterPerNodeForRemoteCapablePool(clusterState, allocation, true);
68+
nodeReplicaCounter = getShardCounterPerNodeForRemoteCapablePool(clusterState, allocation, false);
4369
for (RoutingNode node : routingNodes) {
4470
if (RoutingPool.REMOTE_CAPABLE.equals(RoutingPool.getNodePool(node))) {
45-
assertInRange(nodePrimariesCounter.get(node.nodeId()), avgPrimariesPerNode, remoteCapableNodes - 1);
46-
assertTrue(nodeReplicaCounter.get(node.nodeId()) >= 0);
71+
assertEquals(avgPrimariesPerNode, (int) nodePrimariesCounter.get(node.nodeId()));
72+
assertTrue(nodeReplicaCounter.getOrDefault(node.nodeId(), 0) >= 0);
4773
}
4874
}
4975
}

settings.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111

1212
plugins {
13-
id "com.gradle.develocity" version "3.18.2"
13+
id "com.gradle.develocity" version "3.19"
1414
}
1515

1616
ext.disableBuildCache = hasProperty('DISABLE_BUILD_CACHE') || System.getenv().containsKey('DISABLE_BUILD_CACHE')

0 commit comments

Comments
 (0)