Skip to content

Commit ec34737

Browse files
authored
[Remove] Legacy Version support from Snapshot/Restore Service (#4728)
Removes all stale snapshot / restore code for legacy versions prior to OpenSearch 2.0. This includes handling null ShardGenerations, partial concurrency, null index generations, etc. which are no longer supported in snapshot versions after legacy 7.5. Signed-off-by: Nicholas Walter Knize <[email protected]>
1 parent eb33015 commit ec34737

File tree

20 files changed

+160
-972
lines changed

20 files changed

+160
-972
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
9999
- Remove LegacyESVersion.V_7_2_ and V_7_3_ Constants ([#4702](https://github.com/opensearch-project/OpenSearch/pull/4702))
100100
- Always auto release the flood stage block ([#4703](https://github.com/opensearch-project/OpenSearch/pull/4703))
101101
- Remove LegacyESVersion.V_7_4_ and V_7_5_ Constants ([#4704](https://github.com/opensearch-project/OpenSearch/pull/4704))
102+
- Remove Legacy Version support from Snapshot/Restore Service ([#4728](https://github.com/opensearch-project/OpenSearch/pull/4728))
103+
102104
### Fixed
103105
- `opensearch-service.bat start` and `opensearch-service.bat manager` failing to run ([#4289](https://github.com/opensearch-project/OpenSearch/pull/4289))
104106
- PR reference to checkout code for changelog verifier ([#4296](https://github.com/opensearch-project/OpenSearch/pull/4296))

plugins/repository-s3/src/internalClusterTest/java/org/opensearch/repositories/s3/S3BlobStoreRepositoryTests.java

-64
Original file line numberDiff line numberDiff line change
@@ -36,56 +36,42 @@
3636
import com.sun.net.httpserver.HttpExchange;
3737
import com.sun.net.httpserver.HttpHandler;
3838
import fixture.s3.S3HttpHandler;
39-
import org.opensearch.action.ActionRunnable;
40-
import org.opensearch.action.support.PlainActionFuture;
4139

4240
import org.opensearch.cluster.metadata.RepositoryMetadata;
4341
import org.opensearch.cluster.service.ClusterService;
4442
import org.opensearch.common.SuppressForbidden;
4543
import org.opensearch.common.blobstore.BlobContainer;
4644
import org.opensearch.common.blobstore.BlobPath;
4745
import org.opensearch.common.blobstore.BlobStore;
48-
import org.opensearch.common.bytes.BytesReference;
4946
import org.opensearch.common.regex.Regex;
5047
import org.opensearch.common.settings.MockSecureSettings;
5148
import org.opensearch.common.settings.Setting;
5249
import org.opensearch.common.settings.Settings;
5350
import org.opensearch.common.unit.ByteSizeUnit;
54-
import org.opensearch.common.unit.TimeValue;
5551
import org.opensearch.common.xcontent.NamedXContentRegistry;
56-
import org.opensearch.common.xcontent.XContentFactory;
5752
import org.opensearch.indices.recovery.RecoverySettings;
5853
import org.opensearch.plugins.Plugin;
59-
import org.opensearch.repositories.RepositoriesService;
60-
import org.opensearch.repositories.RepositoryData;
6154
import org.opensearch.repositories.blobstore.BlobStoreRepository;
6255
import org.opensearch.repositories.blobstore.OpenSearchMockAPIBasedRepositoryIntegTestCase;
63-
import org.opensearch.snapshots.SnapshotId;
64-
import org.opensearch.snapshots.SnapshotsService;
6556
import org.opensearch.snapshots.mockstore.BlobStoreWrapper;
6657
import org.opensearch.test.OpenSearchIntegTestCase;
6758
import org.opensearch.threadpool.ThreadPool;
6859

6960
import java.io.IOException;
70-
import java.io.InputStream;
7161
import java.util.ArrayList;
7262
import java.util.Collection;
7363
import java.util.Collections;
7464
import java.util.List;
7565
import java.util.Map;
7666

7767
import static org.hamcrest.Matchers.containsString;
78-
import static org.hamcrest.Matchers.greaterThan;
79-
import static org.hamcrest.Matchers.lessThan;
8068
import static org.hamcrest.Matchers.startsWith;
8169

8270
@SuppressForbidden(reason = "this test uses a HttpServer to emulate an S3 endpoint")
8371
// Need to set up a new cluster for each test because cluster settings use randomized authentication settings
8472
@OpenSearchIntegTestCase.ClusterScope(scope = OpenSearchIntegTestCase.Scope.TEST)
8573
public class S3BlobStoreRepositoryTests extends OpenSearchMockAPIBasedRepositoryIntegTestCase {
8674

87-
private static final TimeValue TEST_COOLDOWN_PERIOD = TimeValue.timeValueSeconds(10L);
88-
8975
private String region;
9076
private String signerOverride;
9177

@@ -158,56 +144,6 @@ protected Settings nodeSettings(int nodeOrdinal) {
158144
return builder.build();
159145
}
160146

161-
public void testEnforcedCooldownPeriod() throws IOException {
162-
final String repoName = createRepository(
163-
randomName(),
164-
Settings.builder().put(repositorySettings()).put(S3Repository.COOLDOWN_PERIOD.getKey(), TEST_COOLDOWN_PERIOD).build()
165-
);
166-
167-
final SnapshotId fakeOldSnapshot = client().admin()
168-
.cluster()
169-
.prepareCreateSnapshot(repoName, "snapshot-old")
170-
.setWaitForCompletion(true)
171-
.setIndices()
172-
.get()
173-
.getSnapshotInfo()
174-
.snapshotId();
175-
final RepositoriesService repositoriesService = internalCluster().getCurrentClusterManagerNodeInstance(RepositoriesService.class);
176-
final BlobStoreRepository repository = (BlobStoreRepository) repositoriesService.repository(repoName);
177-
final RepositoryData repositoryData = getRepositoryData(repository);
178-
final RepositoryData modifiedRepositoryData = repositoryData.withVersions(
179-
Collections.singletonMap(fakeOldSnapshot, SnapshotsService.SHARD_GEN_IN_REPO_DATA_VERSION.minimumCompatibilityVersion())
180-
);
181-
final BytesReference serialized = BytesReference.bytes(
182-
modifiedRepositoryData.snapshotsToXContent(XContentFactory.jsonBuilder(), SnapshotsService.OLD_SNAPSHOT_FORMAT)
183-
);
184-
PlainActionFuture.get(f -> repository.threadPool().generic().execute(ActionRunnable.run(f, () -> {
185-
try (InputStream stream = serialized.streamInput()) {
186-
repository.blobStore()
187-
.blobContainer(repository.basePath())
188-
.writeBlobAtomic(
189-
BlobStoreRepository.INDEX_FILE_PREFIX + modifiedRepositoryData.getGenId(),
190-
stream,
191-
serialized.length(),
192-
true
193-
);
194-
}
195-
})));
196-
197-
final String newSnapshotName = "snapshot-new";
198-
final long beforeThrottledSnapshot = repository.threadPool().relativeTimeInNanos();
199-
client().admin().cluster().prepareCreateSnapshot(repoName, newSnapshotName).setWaitForCompletion(true).setIndices().get();
200-
assertThat(repository.threadPool().relativeTimeInNanos() - beforeThrottledSnapshot, greaterThan(TEST_COOLDOWN_PERIOD.getNanos()));
201-
202-
final long beforeThrottledDelete = repository.threadPool().relativeTimeInNanos();
203-
client().admin().cluster().prepareDeleteSnapshot(repoName, newSnapshotName).get();
204-
assertThat(repository.threadPool().relativeTimeInNanos() - beforeThrottledDelete, greaterThan(TEST_COOLDOWN_PERIOD.getNanos()));
205-
206-
final long beforeFastDelete = repository.threadPool().relativeTimeInNanos();
207-
client().admin().cluster().prepareDeleteSnapshot(repoName, fakeOldSnapshot.getName()).get();
208-
assertThat(repository.threadPool().relativeTimeInNanos() - beforeFastDelete, lessThan(TEST_COOLDOWN_PERIOD.getNanos()));
209-
}
210-
211147
/**
212148
* S3RepositoryPlugin that allows to disable chunked encoding and to set a low threshold between single upload and multipart upload.
213149
*/

plugins/repository-s3/src/main/java/org/opensearch/repositories/s3/S3Repository.java

-85
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,8 @@
3535
import org.apache.logging.log4j.LogManager;
3636
import org.apache.logging.log4j.Logger;
3737

38-
import org.opensearch.LegacyESVersion;
3938
import org.opensearch.Version;
4039
import org.opensearch.action.ActionListener;
41-
import org.opensearch.action.ActionRunnable;
4240
import org.opensearch.cluster.ClusterState;
4341
import org.opensearch.cluster.metadata.Metadata;
4442
import org.opensearch.cluster.metadata.RepositoryMetadata;
@@ -52,7 +50,6 @@
5250
import org.opensearch.common.settings.Setting;
5351
import org.opensearch.common.unit.ByteSizeUnit;
5452
import org.opensearch.common.unit.ByteSizeValue;
55-
import org.opensearch.common.unit.TimeValue;
5653
import org.opensearch.common.xcontent.NamedXContentRegistry;
5754
import org.opensearch.indices.recovery.RecoverySettings;
5855
import org.opensearch.monitor.jvm.JvmInfo;
@@ -62,13 +59,10 @@
6259
import org.opensearch.repositories.blobstore.MeteredBlobStoreRepository;
6360
import org.opensearch.snapshots.SnapshotId;
6461
import org.opensearch.snapshots.SnapshotInfo;
65-
import org.opensearch.snapshots.SnapshotsService;
6662
import org.opensearch.threadpool.Scheduler;
67-
import org.opensearch.threadpool.ThreadPool;
6863

6964
import java.util.Collection;
7065
import java.util.Map;
71-
import java.util.concurrent.TimeUnit;
7266
import java.util.concurrent.atomic.AtomicReference;
7367
import java.util.function.Function;
7468

@@ -182,24 +176,6 @@ class S3Repository extends MeteredBlobStoreRepository {
182176

183177
static final Setting<String> CLIENT_NAME = new Setting<>("client", "default", Function.identity());
184178

185-
/**
186-
* Artificial delay to introduce after a snapshot finalization or delete has finished so long as the repository is still using the
187-
* backwards compatible snapshot format from before
188-
* {@link org.opensearch.snapshots.SnapshotsService#SHARD_GEN_IN_REPO_DATA_VERSION} ({@link LegacyESVersion#V_7_6_0}).
189-
* This delay is necessary so that the eventually consistent nature of AWS S3 does not randomly result in repository corruption when
190-
* doing repository operations in rapid succession on a repository in the old metadata format.
191-
* This setting should not be adjusted in production when working with an AWS S3 backed repository. Doing so risks the repository
192-
* becoming silently corrupted. To get rid of this waiting period, either create a new S3 repository or remove all snapshots older than
193-
* {@link LegacyESVersion#V_7_6_0} from the repository which will trigger an upgrade of the repository metadata to the new
194-
* format and disable the cooldown period.
195-
*/
196-
static final Setting<TimeValue> COOLDOWN_PERIOD = Setting.timeSetting(
197-
"cooldown_period",
198-
new TimeValue(3, TimeUnit.MINUTES),
199-
new TimeValue(0, TimeUnit.MILLISECONDS),
200-
Setting.Property.Dynamic
201-
);
202-
203179
/**
204180
* Specifies the path within bucket to repository data. Defaults to root directory.
205181
*/
@@ -223,12 +199,6 @@ class S3Repository extends MeteredBlobStoreRepository {
223199

224200
private final RepositoryMetadata repositoryMetadata;
225201

226-
/**
227-
* Time period to delay repository operations by after finalizing or deleting a snapshot.
228-
* See {@link #COOLDOWN_PERIOD} for details.
229-
*/
230-
private final TimeValue coolDown;
231-
232202
/**
233203
* Constructs an s3 backed repository
234204
*/
@@ -296,8 +266,6 @@ class S3Repository extends MeteredBlobStoreRepository {
296266
);
297267
}
298268

299-
coolDown = COOLDOWN_PERIOD.get(metadata.settings());
300-
301269
logger.debug(
302270
"using bucket [{}], chunk_size [{}], server_side_encryption [{}], buffer_size [{}], cannedACL [{}], storageClass [{}]",
303271
bucket,
@@ -334,9 +302,6 @@ public void finalizeSnapshot(
334302
Function<ClusterState, ClusterState> stateTransformer,
335303
ActionListener<RepositoryData> listener
336304
) {
337-
if (SnapshotsService.useShardGenerations(repositoryMetaVersion) == false) {
338-
listener = delayedListener(listener);
339-
}
340305
super.finalizeSnapshot(
341306
shardGenerations,
342307
repositoryStateId,
@@ -355,59 +320,9 @@ public void deleteSnapshots(
355320
Version repositoryMetaVersion,
356321
ActionListener<RepositoryData> listener
357322
) {
358-
if (SnapshotsService.useShardGenerations(repositoryMetaVersion) == false) {
359-
listener = delayedListener(listener);
360-
}
361323
super.deleteSnapshots(snapshotIds, repositoryStateId, repositoryMetaVersion, listener);
362324
}
363325

364-
/**
365-
* Wraps given listener such that it is executed with a delay of {@link #coolDown} on the snapshot thread-pool after being invoked.
366-
* See {@link #COOLDOWN_PERIOD} for details.
367-
*/
368-
private <T> ActionListener<T> delayedListener(ActionListener<T> listener) {
369-
final ActionListener<T> wrappedListener = ActionListener.runBefore(listener, () -> {
370-
final Scheduler.Cancellable cancellable = finalizationFuture.getAndSet(null);
371-
assert cancellable != null;
372-
});
373-
return new ActionListener<T>() {
374-
@Override
375-
public void onResponse(T response) {
376-
logCooldownInfo();
377-
final Scheduler.Cancellable existing = finalizationFuture.getAndSet(
378-
threadPool.schedule(
379-
ActionRunnable.wrap(wrappedListener, l -> l.onResponse(response)),
380-
coolDown,
381-
ThreadPool.Names.SNAPSHOT
382-
)
383-
);
384-
assert existing == null : "Already have an ongoing finalization " + finalizationFuture;
385-
}
386-
387-
@Override
388-
public void onFailure(Exception e) {
389-
logCooldownInfo();
390-
final Scheduler.Cancellable existing = finalizationFuture.getAndSet(
391-
threadPool.schedule(ActionRunnable.wrap(wrappedListener, l -> l.onFailure(e)), coolDown, ThreadPool.Names.SNAPSHOT)
392-
);
393-
assert existing == null : "Already have an ongoing finalization " + finalizationFuture;
394-
}
395-
};
396-
}
397-
398-
private void logCooldownInfo() {
399-
logger.info(
400-
"Sleeping for [{}] after modifying repository [{}] because it contains snapshots older than version [{}]"
401-
+ " and therefore is using a backwards compatible metadata format that requires this cooldown period to avoid "
402-
+ "repository corruption. To get rid of this message and move to the new repository metadata format, either remove "
403-
+ "all snapshots older than version [{}] from the repository or create a new repository at an empty location.",
404-
coolDown,
405-
metadata.name(),
406-
SnapshotsService.SHARD_GEN_IN_REPO_DATA_VERSION,
407-
SnapshotsService.SHARD_GEN_IN_REPO_DATA_VERSION
408-
);
409-
}
410-
411326
@Override
412327
protected S3BlobStore createBlobStore() {
413328
return new S3BlobStore(service, bucket, serverSideEncryption, bufferSize, cannedACL, storageClass, repositoryMetadata);

qa/repository-multi-version/src/test/java/org/opensearch/upgrades/MultiVersionRepositoryAccessIT.java

+4-18
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
package org.opensearch.upgrades;
3434

35-
import org.opensearch.OpenSearchStatusException;
3635
import org.opensearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
3736
import org.opensearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
3837
import org.opensearch.action.admin.cluster.snapshots.status.SnapshotStatus;
@@ -42,20 +41,17 @@
4241
import org.opensearch.client.Request;
4342
import org.opensearch.client.RequestOptions;
4443
import org.opensearch.client.Response;
45-
import org.opensearch.client.ResponseException;
4644
import org.opensearch.client.RestClient;
4745
import org.opensearch.client.RestHighLevelClient;
4846
import org.opensearch.common.settings.Settings;
4947
import org.opensearch.common.xcontent.DeprecationHandler;
5048
import org.opensearch.common.xcontent.XContentParser;
5149
import org.opensearch.common.xcontent.json.JsonXContent;
52-
import org.opensearch.snapshots.SnapshotsService;
5350
import org.opensearch.test.rest.OpenSearchRestTestCase;
5451

5552
import java.io.IOException;
5653
import java.io.InputStream;
5754
import java.net.HttpURLConnection;
58-
import java.util.Arrays;
5955
import java.util.List;
6056
import java.util.Map;
6157
import java.util.stream.Collectors;
@@ -231,20 +227,10 @@ public void testUpgradeMovesRepoToNewMetaVersion() throws IOException {
231227
ensureSnapshotRestoreWorks(repoName, "snapshot-2", shards);
232228
}
233229
} else {
234-
if (SnapshotsService.useIndexGenerations(minimumNodeVersion()) == false) {
235-
assertThat(TEST_STEP, is(TestStep.STEP3_OLD_CLUSTER));
236-
final List<Class<? extends Exception>> expectedExceptions =
237-
Arrays.asList(ResponseException.class, OpenSearchStatusException.class);
238-
expectThrowsAnyOf(expectedExceptions, () -> listSnapshots(repoName));
239-
expectThrowsAnyOf(expectedExceptions, () -> deleteSnapshot(client, repoName, "snapshot-1"));
240-
expectThrowsAnyOf(expectedExceptions, () -> deleteSnapshot(client, repoName, "snapshot-2"));
241-
expectThrowsAnyOf(expectedExceptions, () -> createSnapshot(client, repoName, "snapshot-impossible", index));
242-
} else {
243-
assertThat(listSnapshots(repoName), hasSize(2));
244-
if (TEST_STEP == TestStep.STEP4_NEW_CLUSTER) {
245-
ensureSnapshotRestoreWorks(repoName, "snapshot-1", shards);
246-
ensureSnapshotRestoreWorks(repoName, "snapshot-2", shards);
247-
}
230+
assertThat(listSnapshots(repoName), hasSize(2));
231+
if (TEST_STEP == TestStep.STEP4_NEW_CLUSTER) {
232+
ensureSnapshotRestoreWorks(repoName, "snapshot-1", shards);
233+
ensureSnapshotRestoreWorks(repoName, "snapshot-2", shards);
248234
}
249235
}
250236
} finally {

server/src/internalClusterTest/java/org/opensearch/snapshots/CloneSnapshotIT.java

+1-19
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,6 @@ public void testShardClone() throws Exception {
7878
final Path repoPath = randomRepoPath();
7979
createRepository(repoName, "fs", repoPath);
8080

81-
final boolean useBwCFormat = randomBoolean();
82-
if (useBwCFormat) {
83-
initWithSnapshotVersion(repoName, repoPath, SnapshotsService.OLD_SNAPSHOT_FORMAT);
84-
// Re-create repo to clear repository data cache
85-
assertAcked(clusterAdmin().prepareDeleteRepository(repoName).get());
86-
createRepository(repoName, "fs", repoPath);
87-
}
88-
8981
final String indexName = "test-index";
9082
createIndexWithRandomDocs(indexName, randomIntBetween(5, 10));
9183
final String sourceSnapshot = "source-snapshot";
@@ -101,21 +93,11 @@ public void testShardClone() throws Exception {
10193

10294
final SnapshotId targetSnapshotId = new SnapshotId("target-snapshot", UUIDs.randomBase64UUID(random()));
10395

104-
final String currentShardGen;
105-
if (useBwCFormat) {
106-
currentShardGen = null;
107-
} else {
108-
currentShardGen = repositoryData.shardGenerations().getShardGen(indexId, shardId);
109-
}
96+
final String currentShardGen = repositoryData.shardGenerations().getShardGen(indexId, shardId);
11097
final String newShardGeneration = PlainActionFuture.get(
11198
f -> repository.cloneShardSnapshot(sourceSnapshotInfo.snapshotId(), targetSnapshotId, repositoryShardId, currentShardGen, f)
11299
);
113100

114-
if (useBwCFormat) {
115-
final long gen = Long.parseLong(newShardGeneration);
116-
assertEquals(gen, 1L); // Initial snapshot brought it to 0, clone increments it to 1
117-
}
118-
119101
final BlobStoreIndexShardSnapshot targetShardSnapshot = readShardSnapshot(repository, repositoryShardId, targetSnapshotId);
120102
final BlobStoreIndexShardSnapshot sourceShardSnapshot = readShardSnapshot(
121103
repository,

0 commit comments

Comments
 (0)