From c0129ebcc2a2f2c7c70e295205a5f5be9eb0795e Mon Sep 17 00:00:00 2001 From: Igor Motov Date: Fri, 3 Oct 2014 13:23:11 -0400 Subject: [PATCH] Snapshot/Restore: make it possible to delete snapshots with missing metadata file Fixes #7980 --- .../blobstore/BlobStoreRepository.java | 23 +++++++++--- .../SharedClusterSnapshotRestoreTests.java | 35 +++++++++++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java b/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java index 65fc3ad1a7468..3233b38d7520b 100644 --- a/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java +++ b/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java @@ -44,6 +44,7 @@ import org.elasticsearch.common.unit.ByteSizeUnit; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.xcontent.*; +import org.elasticsearch.index.shard.IndexShardException; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.index.snapshots.IndexShardRepository; import org.elasticsearch.index.snapshots.blobstore.BlobStoreIndexShardRepository; @@ -262,7 +263,12 @@ public void initializeSnapshot(SnapshotId snapshotId, ImmutableList indi @Override public void deleteSnapshot(SnapshotId snapshotId) { Snapshot snapshot = readSnapshot(snapshotId); - MetaData metaData = readSnapshotMetaData(snapshotId, snapshot.indices(), true); + MetaData metaData = null; + try { + metaData = readSnapshotMetaData(snapshotId, snapshot.indices(), true); + } catch (SnapshotException ex) { + logger.warn("cannot read metadata for snapshot [{}]", ex, snapshotId); + } try { String blobName = snapshotBlobName(snapshotId); // Delete snapshot file first so we wouldn't end up with partially deleted snapshot that looks OK @@ -289,10 +295,17 @@ public void deleteSnapshot(SnapshotId snapshotId) { } catch (IOException ex) { logger.warn("[{}] failed to delete metadata for index [{}]", ex, snapshotId, index); } - IndexMetaData indexMetaData = metaData.index(index); - if (indexMetaData != null) { - for (int i = 0; i < indexMetaData.getNumberOfShards(); i++) { - indexShardRepository.delete(snapshotId, new ShardId(index, i)); + if (metaData != null) { + IndexMetaData indexMetaData = metaData.index(index); + if (indexMetaData != null) { + for (int i = 0; i < indexMetaData.getNumberOfShards(); i++) { + ShardId shardId = new ShardId(index, i); + try { + indexShardRepository.delete(snapshotId, shardId); + } catch (IndexShardException | SnapshotException ex) { + logger.warn("[{}] failed to delete shard data for shard [{}]", ex, snapshotId, shardId); + } + } } } } diff --git a/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreTests.java b/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreTests.java index 3fd25637902e0..48dbfb5d01e19 100644 --- a/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreTests.java +++ b/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreTests.java @@ -740,6 +740,41 @@ public void deleteSnapshotWithMissingIndexAndShardMetadataTest() throws Exceptio assertThrows(client.admin().cluster().prepareGetSnapshots("test-repo").addSnapshots("test-snap-1"), SnapshotMissingException.class); } + @Test + public void deleteSnapshotWithMissingMetadataTest() throws Exception { + Client client = client(); + + File repo = newTempDir(LifecycleScope.SUITE); + logger.info("--> creating repository at " + repo.getAbsolutePath()); + assertAcked(client.admin().cluster().preparePutRepository("test-repo") + .setType("fs").setSettings(ImmutableSettings.settingsBuilder() + .put("location", repo) + .put("compress", false) + .put("chunk_size", randomIntBetween(100, 1000)))); + + createIndex("test-idx-1", "test-idx-2"); + ensureYellow(); + logger.info("--> indexing some data"); + indexRandom(true, + client().prepareIndex("test-idx-1", "doc").setSource("foo", "bar"), + client().prepareIndex("test-idx-2", "doc").setSource("foo", "bar")); + + logger.info("--> creating snapshot"); + CreateSnapshotResponse createSnapshotResponse = client.admin().cluster().prepareCreateSnapshot("test-repo", "test-snap-1").setWaitForCompletion(true).setIndices("test-idx-*").get(); + assertThat(createSnapshotResponse.getSnapshotInfo().successfulShards(), greaterThan(0)); + assertThat(createSnapshotResponse.getSnapshotInfo().successfulShards(), equalTo(createSnapshotResponse.getSnapshotInfo().totalShards())); + + logger.info("--> delete index metadata and shard metadata"); + File metadata = new File(repo, "metadata-test-snap-1"); + assertThat(metadata.delete(), equalTo(true)); + + logger.info("--> delete snapshot"); + client.admin().cluster().prepareDeleteSnapshot("test-repo", "test-snap-1").get(); + + logger.info("--> make sure snapshot doesn't exist"); + assertThrows(client.admin().cluster().prepareGetSnapshots("test-repo").addSnapshots("test-snap-1"), SnapshotMissingException.class); + } + @Test @TestLogging("snapshots:TRACE") public void snapshotClosedIndexTest() throws Exception {