diff --git a/server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java b/server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java index 717efda1b79..3318c6ab46c 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java +++ b/server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java @@ -210,6 +210,9 @@ public class SnapshotsService extends AbstractLifecycleComponent implements Clus if (ignoreUnavailable) { logger.warn(() -> new ParameterizedMessage("failed to get snapshot [{}]", snapshotId), ex); } else { + if (ex instanceof SnapshotException) { + throw ex; + } throw new SnapshotException(repositoryName, snapshotId, "Snapshot could not be read", ex); } } diff --git a/server/src/test/java/org/elasticsearch/snapshots/SnapshotStatusApisIT.java b/server/src/test/java/org/elasticsearch/snapshots/SnapshotStatusApisIT.java index 7d82e0514d1..9a688197a3b 100644 --- a/server/src/test/java/org/elasticsearch/snapshots/SnapshotStatusApisIT.java +++ b/server/src/test/java/org/elasticsearch/snapshots/SnapshotStatusApisIT.java @@ -21,13 +21,18 @@ package org.elasticsearch.snapshots; import org.elasticsearch.Version; import org.elasticsearch.action.ActionFuture; import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse; +import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest; import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotStatus; import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusRequest; import org.elasticsearch.client.Client; import org.elasticsearch.cluster.SnapshotsInProgress; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.core.internal.io.IOUtils; +import org.elasticsearch.repositories.blobstore.BlobStoreRepository; +import java.io.IOException; +import java.nio.file.Path; import java.util.List; import java.util.concurrent.TimeUnit; @@ -109,4 +114,23 @@ public class SnapshotStatusApisIT extends AbstractSnapshotIntegTestCase { logger.info("--> wait for snapshot to finish"); createSnapshotResponseActionFuture.actionGet(); } + + public void testExceptionOnMissingSnapBlob() throws IOException { + disableRepoConsistencyCheck("This test intentionally corrupts the repository"); + + logger.info("--> creating repository"); + final Path repoPath = randomRepoPath(); + assertAcked(client().admin().cluster().preparePutRepository("test-repo").setType("fs").setSettings( + Settings.builder().put("location", repoPath).build())); + + logger.info("--> snapshot"); + final CreateSnapshotResponse response = + client().admin().cluster().prepareCreateSnapshot("test-repo", "test-snap").setWaitForCompletion(true).get(); + + logger.info("--> delete snap-${uuid}.dat file for this snapshot to simulate concurrent delete"); + IOUtils.rm(repoPath.resolve(BlobStoreRepository.SNAPSHOT_PREFIX + response.getSnapshotInfo().snapshotId().getUUID() + ".dat")); + + expectThrows(SnapshotMissingException.class, () -> client().admin().cluster() + .getSnapshots(new GetSnapshotsRequest("test-repo", new String[] {"test-snap"})).actionGet()); + } }