Skip to content

Commit e2cb334

Browse files
Merge branch 'main' of https://github.com/Jan-Kazlouski-elastic/elasticsearch into feature/hugging-face-chat-completion-integration
2 parents e72a312 + 7e22bb5 commit e2cb334

File tree

12 files changed

+316
-39
lines changed

12 files changed

+316
-39
lines changed

docs/release-notes/breaking-changes.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ will prevent node from starting [#118366](https://github.com/elastic/elasticsear
3939
Cluster Coordination:
4040
* Remove unsupported legacy value for `discovery.type` [#112903](https://github.com/elastic/elasticsearch/pull/112903)
4141

42+
ES|QL
43+
* Limit the scope of the skip_unavailable setting for remote clusters [#120236](https://github.com/elastic/elasticsearch/pull/120236)
44+
4245
EQL:
4346
* Set allow_partial_search_results=true by default [#120267](https://github.com/elastic/elasticsearch/pull/120267)
4447

modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/DataStreamAutoshardingIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ private static ShardStats getShardStats(IndexMetadata indexMeta, int shardIndex,
528528
stats.docs = new DocsStats(100, 0, randomByteSizeValue().getBytes());
529529
stats.store = new StoreStats();
530530
stats.indexing = new IndexingStats(
531-
new IndexingStats.Stats(1, 1, 1, 1, 1, 1, 1, 1, 1, false, 1, targetWriteLoad, targetWriteLoad, 1, 0.123, 0.234)
531+
new IndexingStats.Stats(1, 1, 1, 1, 1, 1, 1, 1, 1, false, 1, 234, 234, 1000, 0.123, targetWriteLoad)
532532
);
533533
return new ShardStats(shardRouting, new ShardPath(false, path, path, shardId), stats, null, null, null, false, 0);
534534
}

muted-tests.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -447,9 +447,6 @@ tests:
447447
- class: org.elasticsearch.xpack.esql.qa.mixed.EsqlClientYamlIT
448448
method: test {p0=esql/120_profile/avg 8.14 or after}
449449
issue: https://github.com/elastic/elasticsearch/issues/127879
450-
- class: org.elasticsearch.cluster.routing.allocation.decider.DiskThresholdDeciderIT
451-
method: testRestoreSnapshotAllocationDoesNotExceedWatermarkWithMultipleRestores
452-
issue: https://github.com/elastic/elasticsearch/issues/127787
453450
- class: org.elasticsearch.indices.stats.IndexStatsIT
454451
method: testThrottleStats
455452
issue: https://github.com/elastic/elasticsearch/issues/126359
@@ -477,6 +474,15 @@ tests:
477474
- class: org.elasticsearch.compute.aggregation.SampleDoubleAggregatorFunctionTests
478475
method: testSimpleWithCranky
479476
issue: https://github.com/elastic/elasticsearch/issues/128024
477+
- class: org.elasticsearch.xpack.esql.qa.multi_node.EsqlSpecIT
478+
method: test {lookup-join.MvJoinKeyOnTheLookupIndex ASYNC}
479+
issue: https://github.com/elastic/elasticsearch/issues/128030
480+
- class: org.elasticsearch.packaging.test.DockerTests
481+
method: test072RunEsAsDifferentUserAndGroup
482+
issue: https://github.com/elastic/elasticsearch/issues/128031
483+
- class: org.elasticsearch.packaging.test.DockerTests
484+
method: test042KeystorePermissionsAreCorrect
485+
issue: https://github.com/elastic/elasticsearch/issues/128019
480486

481487
# Examples:
482488
#

server/src/internalClusterTest/java/org/elasticsearch/cluster/routing/allocation/decider/DiskThresholdDeciderIT.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,12 @@ public void testRestoreSnapshotAllocationDoesNotExceedWatermarkWithMultipleResto
280280
tinyNodeShardIds.size() + tinyNodeShardIdsCopy.size(),
281281
is(1)
282282
);
283-
assertThat(tinyNodeShardIds.iterator().next(), in(shardSizes.getShardIdsWithSizeSmallerOrEqual(usableSpace)));
283+
final var useableSpaceShardSizes = shardSizes.getShardIdsWithSizeSmallerOrEqual(usableSpace);
284+
final var tinyNodeShardId = tinyNodeShardIds.isEmpty() == false
285+
? tinyNodeShardIds.iterator().next()
286+
// shardSizes only contains the sizes from the original index, not the copy, so we map the copied shard back to the original idx
287+
: new ShardId(useableSpaceShardSizes.iterator().next().getIndex(), tinyNodeShardIdsCopy.iterator().next().id());
288+
assertThat(tinyNodeShardId, in(useableSpaceShardSizes));
284289
}
285290

286291
private Set<ShardId> getShardIds(final String nodeId, final String indexName) {

server/src/main/java/org/elasticsearch/action/admin/cluster/repositories/cleanup/TransportCleanupRepositoryAction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ private void cleanupRepo(String repositoryName, ActionListener<RepositoryCleanup
171171
@Override
172172
public ClusterState execute(ClusterState currentState) {
173173
SnapshotsService.ensureRepositoryExists(repositoryName, currentState);
174+
SnapshotsService.ensureNotReadOnly(currentState, repositoryName);
174175
final RepositoryCleanupInProgress repositoryCleanupInProgress = RepositoryCleanupInProgress.get(currentState);
175176
if (repositoryCleanupInProgress.hasCleanupInProgress()) {
176177
throw new IllegalStateException(

server/src/main/java/org/elasticsearch/action/datastreams/autosharding/DataStreamAutoShardingService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public enum WriteLoadMetric {
136136
public static final Setting<WriteLoadMetric> DATA_STREAMS_AUTO_SHARDING_INCREASE_SHARDS_LOAD_METRIC = Setting.enumSetting(
137137
WriteLoadMetric.class,
138138
"data_streams.auto_sharding.increase_shards.load_metric",
139-
WriteLoadMetric.ALL_TIME,
139+
WriteLoadMetric.PEAK,
140140
Setting.Property.Dynamic,
141141
Setting.Property.NodeScope
142142
);
@@ -147,7 +147,7 @@ public enum WriteLoadMetric {
147147
public static final Setting<WriteLoadMetric> DATA_STREAMS_AUTO_SHARDING_DECREASE_SHARDS_LOAD_METRIC = Setting.enumSetting(
148148
WriteLoadMetric.class,
149149
"data_streams.auto_sharding.decrease_shards.load_metric",
150-
WriteLoadMetric.ALL_TIME,
150+
WriteLoadMetric.PEAK,
151151
Setting.Property.Dynamic,
152152
Setting.Property.NodeScope
153153
);

server/src/main/java/org/elasticsearch/repositories/RepositoriesService.java

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.elasticsearch.index.Index;
5151
import org.elasticsearch.index.IndexVersion;
5252
import org.elasticsearch.repositories.VerifyNodeRepositoryAction.Request;
53+
import org.elasticsearch.repositories.blobstore.BlobStoreRepository;
5354
import org.elasticsearch.repositories.blobstore.MeteredBlobStoreRepository;
5455
import org.elasticsearch.snapshots.Snapshot;
5556
import org.elasticsearch.threadpool.ThreadPool;
@@ -289,6 +290,7 @@ public ClusterState execute(ClusterState currentState) {
289290
List<RepositoryMetadata> repositoriesMetadata = new ArrayList<>(repositories.repositories().size() + 1);
290291
for (RepositoryMetadata repositoryMetadata : repositories.repositories()) {
291292
if (repositoryMetadata.name().equals(request.name())) {
293+
rejectInvalidReadonlyFlagChange(repositoryMetadata, request.settings());
292294
final RepositoryMetadata newRepositoryMetadata = new RepositoryMetadata(
293295
request.name(),
294296
// Copy the UUID from the existing instance rather than resetting it back to MISSING_UUID which would force us to
@@ -601,6 +603,7 @@ public static boolean isDedicatedVotingOnlyNode(Set<DiscoveryNodeRole> roles) {
601603
public void applyClusterState(ClusterChangedEvent event) {
602604
try {
603605
final ClusterState state = event.state();
606+
assert assertReadonlyRepositoriesNotInUseForWrites(state);
604607
final RepositoriesMetadata oldMetadata = RepositoriesMetadata.get(event.previousState());
605608
final RepositoriesMetadata newMetadata = RepositoriesMetadata.get(state);
606609

@@ -885,7 +888,7 @@ public static void validateRepositoryName(final String repositoryName) {
885888
}
886889
}
887890

888-
private static void ensureRepositoryNotInUse(ClusterState clusterState, String repository) {
891+
private static void ensureRepositoryNotInUseForWrites(ClusterState clusterState, String repository) {
889892
if (SnapshotsInProgress.get(clusterState).forRepo(repository).isEmpty() == false) {
890893
throw newRepositoryConflictException(repository, "snapshot is in progress");
891894
}
@@ -899,13 +902,57 @@ private static void ensureRepositoryNotInUse(ClusterState clusterState, String r
899902
throw newRepositoryConflictException(repository, "repository clean up is in progress");
900903
}
901904
}
905+
}
906+
907+
private static void ensureRepositoryNotInUse(ClusterState clusterState, String repository) {
908+
ensureRepositoryNotInUseForWrites(clusterState, repository);
902909
for (RestoreInProgress.Entry entry : RestoreInProgress.get(clusterState)) {
903910
if (repository.equals(entry.snapshot().getRepository())) {
904911
throw newRepositoryConflictException(repository, "snapshot restore is in progress");
905912
}
906913
}
907914
}
908915

916+
public static boolean isReadOnly(Settings repositorySettings) {
917+
return Boolean.TRUE.equals(repositorySettings.getAsBoolean(BlobStoreRepository.READONLY_SETTING_KEY, null));
918+
}
919+
920+
/**
921+
* Test-only check for the invariant that read-only repositories never have any write activities.
922+
*/
923+
private static boolean assertReadonlyRepositoriesNotInUseForWrites(ClusterState clusterState) {
924+
for (final var repositoryMetadata : RepositoriesMetadata.get(clusterState).repositories()) {
925+
if (isReadOnly(repositoryMetadata.settings())) {
926+
try {
927+
ensureRepositoryNotInUseForWrites(clusterState, repositoryMetadata.name());
928+
} catch (Exception e) {
929+
throw new AssertionError("repository [" + repositoryMetadata + "] is readonly but still in use", e);
930+
}
931+
}
932+
}
933+
return true;
934+
}
935+
936+
/**
937+
* Reject a change to the {@code readonly} setting if there is a pending generation change in progress, i.e. some node somewhere is
938+
* updating the root {@link RepositoryData} blob.
939+
*/
940+
private static void rejectInvalidReadonlyFlagChange(RepositoryMetadata existingRepositoryMetadata, Settings newSettings) {
941+
if (isReadOnly(newSettings)
942+
&& isReadOnly(existingRepositoryMetadata.settings()) == false
943+
&& existingRepositoryMetadata.generation() >= RepositoryData.EMPTY_REPO_GEN
944+
&& existingRepositoryMetadata.generation() != existingRepositoryMetadata.pendingGeneration()) {
945+
throw newRepositoryConflictException(
946+
existingRepositoryMetadata.name(),
947+
Strings.format(
948+
"currently updating root blob generation from [%d] to [%d], cannot update readonly flag",
949+
existingRepositoryMetadata.generation(),
950+
existingRepositoryMetadata.pendingGeneration()
951+
)
952+
);
953+
}
954+
}
955+
909956
private static void ensureNoSearchableSnapshotsIndicesInUse(ClusterState clusterState, RepositoryMetadata repositoryMetadata) {
910957
long count = 0L;
911958
List<Index> indices = null;

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2737,6 +2737,14 @@ protected void writeIndexGen(
27372737
public ClusterState execute(ClusterState currentState) {
27382738
final RepositoryMetadata meta = getRepoMetadata(currentState);
27392739
final String repoName = metadata.name();
2740+
2741+
if (RepositoriesService.isReadOnly(meta.settings())) {
2742+
// Last resort check: we shouldn't have been able to mark the repository as readonly while the operation that led to
2743+
// this writeIndexGen() call was in progress, and conversely shouldn't have started any such operation if the repo
2744+
// was already readonly, but these invariants are not obviously true and it is disastrous to proceed here.
2745+
throw new RepositoryException(meta.name(), "repository is readonly, cannot update root blob");
2746+
}
2747+
27402748
final long genInState = meta.generation();
27412749
final boolean uninitializedMeta = meta.generation() == RepositoryData.UNKNOWN_REPO_GEN || bestEffortConsistency;
27422750
if (uninitializedMeta == false && meta.pendingGeneration() != genInState) {

server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ public ClusterState execute(ClusterState currentState) {
338338
ensureRepositoryExists(repositoryName, currentState);
339339
ensureSnapshotNameAvailableInRepo(repositoryData, snapshotName, repository);
340340
ensureNoCleanupInProgress(currentState, repositoryName, snapshotName, "clone snapshot");
341+
ensureNotReadOnly(currentState, repositoryName);
341342
final SnapshotsInProgress snapshots = SnapshotsInProgress.get(currentState);
342343
ensureSnapshotNameNotRunning(snapshots, repositoryName, snapshotName);
343344
validate(repositoryName, snapshotName, currentState);
@@ -433,6 +434,13 @@ private static void ensureNoCleanupInProgress(
433434
}
434435
}
435436

437+
public static void ensureNotReadOnly(final ClusterState currentState, final String repositoryName) {
438+
final var repositoryMetadata = RepositoriesMetadata.get(currentState).repository(repositoryName);
439+
if (RepositoriesService.isReadOnly(repositoryMetadata.settings())) {
440+
throw new RepositoryException(repositoryMetadata.name(), "repository is readonly");
441+
}
442+
}
443+
436444
private static void ensureSnapshotNameAvailableInRepo(RepositoryData repositoryData, String snapshotName, Repository repository) {
437445
// check if the snapshot name already exists in the repository
438446
if (repositoryData.getSnapshotIds().stream().anyMatch(s -> s.getName().equals(snapshotName))) {
@@ -2166,6 +2174,8 @@ public ClusterState execute(ClusterState currentState) {
21662174
"delete snapshot"
21672175
);
21682176

2177+
ensureNotReadOnly(currentState, repositoryName);
2178+
21692179
final SnapshotDeletionsInProgress deletionsInProgress = SnapshotDeletionsInProgress.get(currentState);
21702180

21712181
final RestoreInProgress restoreInProgress = RestoreInProgress.get(currentState);
@@ -4075,11 +4085,16 @@ public ClusterState execute(BatchExecutionContext<SnapshotTask> batchExecutionCo
40754085
for (final var taskContext : batchExecutionContext.taskContexts()) {
40764086
if (taskContext.getTask() instanceof CreateSnapshotTask task) {
40774087
try {
4088+
final var repoMeta = RepositoriesMetadata.get(state).repository(task.snapshot.getRepository());
4089+
if (RepositoriesService.isReadOnly(repoMeta.settings())) {
4090+
taskContext.onFailure(new RepositoryException(repoMeta.name(), "repository is readonly"));
4091+
continue;
4092+
}
4093+
40784094
registeredPolicySnapshots.addIfSnapshotIsSLMInitiated(
40794095
task.createSnapshotRequest.userMetadata(),
40804096
task.snapshot.getSnapshotId()
40814097
);
4082-
final var repoMeta = RepositoriesMetadata.get(state).repository(task.snapshot.getRepository());
40834098
if (Objects.equals(task.initialRepositoryMetadata, repoMeta)) {
40844099
snapshotsInProgress = createSnapshot(task, taskContext, state, snapshotsInProgress);
40854100
} else {

0 commit comments

Comments
 (0)