Skip to content

Commit 4c7d94c

Browse files
authored
Add prefix mode verification setting for repository verification (#14790) (#14839)
Signed-off-by: Ashish Singh <ssashish@amazon.com>
1 parent e6e62bb commit 4c7d94c

File tree

4 files changed

+72
-5
lines changed

4 files changed

+72
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1818
- Print reason why parent task was cancelled ([#14604](https://github.com/opensearch-project/OpenSearch/issues/14604))
1919
- Add matchesPluginSystemIndexPattern to SystemIndexRegistry ([#14750](https://github.com/opensearch-project/OpenSearch/pull/14750))
2020
- Add Plugin interface for loading application based configuration templates (([#14659](https://github.com/opensearch-project/OpenSearch/issues/14659)))
21+
- Add prefix mode verification setting for repository verification (([#14790](https://github.com/opensearch-project/OpenSearch/pull/14790)))
2122

2223
### Dependencies
2324
- Update to Apache Lucene 9.11.1 ([#14042](https://github.com/opensearch-project/OpenSearch/pull/14042), [#14576](https://github.com/opensearch-project/OpenSearch/pull/14576))

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

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
import org.opensearch.core.xcontent.XContentParser;
110110
import org.opensearch.index.mapper.MapperService;
111111
import org.opensearch.index.remote.RemoteStorePathStrategy;
112+
import org.opensearch.index.remote.RemoteStorePathStrategy.BasePathInput;
112113
import org.opensearch.index.snapshots.IndexShardRestoreFailedException;
113114
import org.opensearch.index.snapshots.IndexShardSnapshotStatus;
114115
import org.opensearch.index.snapshots.blobstore.BlobStoreIndexShardSnapshot;
@@ -158,6 +159,7 @@
158159
import java.util.List;
159160
import java.util.Locale;
160161
import java.util.Map;
162+
import java.util.Objects;
161163
import java.util.Optional;
162164
import java.util.Set;
163165
import java.util.concurrent.BlockingQueue;
@@ -175,6 +177,8 @@
175177
import java.util.stream.LongStream;
176178
import java.util.stream.Stream;
177179

180+
import static org.opensearch.index.remote.RemoteStoreEnums.PathHashAlgorithm.FNV_1A_COMPOSITE_1;
181+
import static org.opensearch.index.remote.RemoteStoreEnums.PathType.HASHED_PREFIX;
178182
import static org.opensearch.index.snapshots.blobstore.BlobStoreIndexShardSnapshot.FileInfo.canonicalName;
179183
import static org.opensearch.repositories.blobstore.ChecksumBlobStoreFormat.SNAPSHOT_ONLY_FORMAT_PARAMS;
180184

@@ -303,6 +307,16 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
303307
Setting.Property.NodeScope
304308
);
305309

310+
/**
311+
* Setting to enable prefix mode verification. In this mode, a hashed string is prepended at the prefix of the base
312+
* path during repository verification.
313+
*/
314+
public static final Setting<Boolean> PREFIX_MODE_VERIFICATION_SETTING = Setting.boolSetting(
315+
"prefix_mode_verification",
316+
false,
317+
Setting.Property.NodeScope
318+
);
319+
306320
protected volatile boolean supportURLRepo;
307321

308322
private volatile int maxShardBlobDeleteBatch;
@@ -370,6 +384,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
370384

371385
private final boolean isSystemRepository;
372386

387+
private final boolean prefixModeVerification;
388+
373389
private final Object lock = new Object();
374390

375391
private final SetOnce<BlobContainer> blobContainer = new SetOnce<>();
@@ -430,6 +446,7 @@ protected BlobStoreRepository(
430446
readRepositoryMetadata(repositoryMetadata);
431447

432448
isSystemRepository = SYSTEM_REPOSITORY_SETTING.get(metadata.settings());
449+
prefixModeVerification = PREFIX_MODE_VERIFICATION_SETTING.get(metadata.settings());
433450
this.namedXContentRegistry = namedXContentRegistry;
434451
this.threadPool = clusterService.getClusterApplierService().threadPool();
435452
this.clusterService = clusterService;
@@ -772,6 +789,10 @@ protected BlobStore getBlobStore() {
772789
return blobStore.get();
773790
}
774791

792+
boolean getPrefixModeVerification() {
793+
return prefixModeVerification;
794+
}
795+
775796
/**
776797
* maintains single lazy instance of {@link BlobContainer}
777798
*/
@@ -2004,7 +2025,7 @@ public String startVerification() {
20042025
} else {
20052026
String seed = UUIDs.randomBase64UUID();
20062027
byte[] testBytes = Strings.toUTF8Bytes(seed);
2007-
BlobContainer testContainer = blobStore().blobContainer(basePath().add(testBlobPrefix(seed)));
2028+
BlobContainer testContainer = testContainer(seed);
20082029
BytesArray bytes = new BytesArray(testBytes);
20092030
if (isSystemRepository == false) {
20102031
try (InputStream stream = bytes.streamInput()) {
@@ -2022,12 +2043,26 @@ public String startVerification() {
20222043
}
20232044
}
20242045

2046+
/**
2047+
* Returns the blobContainer depending on the seed and {@code prefixModeVerification}.
2048+
*/
2049+
private BlobContainer testContainer(String seed) {
2050+
BlobPath testBlobPath;
2051+
if (prefixModeVerification == true) {
2052+
BasePathInput pathInput = BasePathInput.builder().basePath(basePath()).indexUUID(seed).build();
2053+
testBlobPath = HASHED_PREFIX.path(pathInput, FNV_1A_COMPOSITE_1);
2054+
} else {
2055+
testBlobPath = basePath();
2056+
}
2057+
assert Objects.nonNull(testBlobPath);
2058+
return blobStore().blobContainer(testBlobPath.add(testBlobPrefix(seed)));
2059+
}
2060+
20252061
@Override
20262062
public void endVerification(String seed) {
20272063
if (isReadOnly() == false) {
20282064
try {
2029-
final String testPrefix = testBlobPrefix(seed);
2030-
blobStore().blobContainer(basePath().add(testPrefix)).delete();
2065+
testContainer(seed).delete();
20312066
} catch (Exception exp) {
20322067
throw new RepositoryVerificationException(metadata.name(), "cannot delete test data at " + basePath(), exp);
20332068
}
@@ -3404,7 +3439,7 @@ public void verify(String seed, DiscoveryNode localNode) {
34043439
);
34053440
}
34063441
} else {
3407-
BlobContainer testBlobContainer = blobStore().blobContainer(basePath().add(testBlobPrefix(seed)));
3442+
BlobContainer testBlobContainer = testContainer(seed);
34083443
try {
34093444
BytesArray bytes = new BytesArray(seed);
34103445
try (InputStream stream = bytes.streamInput()) {

server/src/test/java/org/opensearch/repositories/blobstore/BlobStoreRepositoryTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,28 @@ public void testBadChunksize() throws Exception {
255255
);
256256
}
257257

258+
public void testPrefixModeVerification() throws Exception {
259+
final Client client = client();
260+
final Path location = OpenSearchIntegTestCase.randomRepoPath(node().settings());
261+
final String repositoryName = "test-repo";
262+
AcknowledgedResponse putRepositoryResponse = client.admin()
263+
.cluster()
264+
.preparePutRepository(repositoryName)
265+
.setType(REPO_TYPE)
266+
.setSettings(
267+
Settings.builder()
268+
.put(node().settings())
269+
.put("location", location)
270+
.put(BlobStoreRepository.PREFIX_MODE_VERIFICATION_SETTING.getKey(), true)
271+
)
272+
.get();
273+
assertTrue(putRepositoryResponse.isAcknowledged());
274+
275+
final RepositoriesService repositoriesService = getInstanceFromNode(RepositoriesService.class);
276+
final BlobStoreRepository repository = (BlobStoreRepository) repositoriesService.repository(repositoryName);
277+
assertTrue(repository.getPrefixModeVerification());
278+
}
279+
258280
public void testFsRepositoryCompressDeprecatedIgnored() {
259281
final Path location = OpenSearchIntegTestCase.randomRepoPath(node().settings());
260282
final Settings settings = Settings.builder().put(node().settings()).put("location", location).build();

test/framework/src/main/java/org/opensearch/test/OpenSearchIntegTestCase.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@
158158
import org.opensearch.node.remotestore.RemoteStoreNodeService;
159159
import org.opensearch.plugins.NetworkPlugin;
160160
import org.opensearch.plugins.Plugin;
161+
import org.opensearch.repositories.blobstore.BlobStoreRepository;
161162
import org.opensearch.repositories.fs.ReloadableFsRepository;
162163
import org.opensearch.script.MockScriptService;
163164
import org.opensearch.script.ScriptMetadata;
@@ -391,8 +392,11 @@ public abstract class OpenSearchIntegTestCase extends OpenSearchTestCase {
391392
CodecService.ZLIB
392393
);
393394

395+
private static Boolean prefixModeVerificationEnable;
396+
394397
@BeforeClass
395398
public static void beforeClass() throws Exception {
399+
prefixModeVerificationEnable = randomBoolean();
396400
testClusterRule.beforeClass();
397401
}
398402

@@ -2664,16 +2668,21 @@ private static Settings buildRemoteStoreNodeAttributes(
26642668
segmentRepoName
26652669
);
26662670

2671+
String prefixModeVerificationSuffix = BlobStoreRepository.PREFIX_MODE_VERIFICATION_SETTING.getKey();
2672+
26672673
Settings.Builder settings = Settings.builder()
26682674
.put("node.attr." + REMOTE_STORE_SEGMENT_REPOSITORY_NAME_ATTRIBUTE_KEY, segmentRepoName)
26692675
.put(segmentRepoTypeAttributeKey, segmentRepoType)
26702676
.put(segmentRepoSettingsAttributeKeyPrefix + "location", segmentRepoPath)
2677+
.put(segmentRepoSettingsAttributeKeyPrefix + prefixModeVerificationSuffix, prefixModeVerificationEnable)
26712678
.put("node.attr." + REMOTE_STORE_TRANSLOG_REPOSITORY_NAME_ATTRIBUTE_KEY, translogRepoName)
26722679
.put(translogRepoTypeAttributeKey, translogRepoType)
26732680
.put(translogRepoSettingsAttributeKeyPrefix + "location", translogRepoPath)
2681+
.put(translogRepoSettingsAttributeKeyPrefix + prefixModeVerificationSuffix, prefixModeVerificationEnable)
26742682
.put("node.attr." + REMOTE_STORE_CLUSTER_STATE_REPOSITORY_NAME_ATTRIBUTE_KEY, segmentRepoName)
26752683
.put(stateRepoTypeAttributeKey, segmentRepoType)
2676-
.put(stateRepoSettingsAttributeKeyPrefix + "location", segmentRepoPath);
2684+
.put(stateRepoSettingsAttributeKeyPrefix + "location", segmentRepoPath)
2685+
.put(stateRepoSettingsAttributeKeyPrefix + prefixModeVerificationSuffix, prefixModeVerificationEnable);
26772686

26782687
if (withRateLimiterAttributes) {
26792688
settings.put(segmentRepoSettingsAttributeKeyPrefix + "compress", randomBoolean())

0 commit comments

Comments
 (0)