Snapshot/Restore: Allow deletion of snapshots with corrupted snapshot files

Improve resiliency of snapshot deletion operation by allowing deletion of snapshot with corrupted snapshot files.

Closes #9534
This commit is contained in:
Igor Motov 2015-02-03 20:27:45 -05:00
parent d479611dc5
commit 73faa2e5ed
2 changed files with 57 additions and 3 deletions

View File

@ -259,10 +259,17 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent<Rep
*/ */
@Override @Override
public void deleteSnapshot(SnapshotId snapshotId) { public void deleteSnapshot(SnapshotId snapshotId) {
Snapshot snapshot = readSnapshot(snapshotId); ImmutableList<String> indices = ImmutableList.of();
try {
indices = readSnapshot(snapshotId).indices();
} catch (SnapshotMissingException ex) {
throw ex;
} catch (SnapshotException | ElasticsearchParseException ex) {
logger.warn("cannot read snapshot file [{}]", ex, snapshotId);
}
MetaData metaData = null; MetaData metaData = null;
try { try {
metaData = readSnapshotMetaData(snapshotId, snapshot.indices(), true); metaData = readSnapshotMetaData(snapshotId, indices, true);
} catch (IOException | SnapshotException ex) { } catch (IOException | SnapshotException ex) {
logger.warn("cannot read metadata for snapshot [{}]", ex, snapshotId); logger.warn("cannot read metadata for snapshot [{}]", ex, snapshotId);
} }
@ -284,7 +291,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent<Rep
} }
writeSnapshotList(snapshotIds); writeSnapshotList(snapshotIds);
// Now delete all indices // Now delete all indices
for (String index : snapshot.indices()) { for (String index : indices) {
BlobPath indexPath = basePath().add("indices").add(index); BlobPath indexPath = basePath().add("indices").add(index);
BlobContainer indexMetaDataBlobContainer = blobStore().blobContainer(indexPath); BlobContainer indexMetaDataBlobContainer = blobStore().blobContainer(indexPath);
try { try {

View File

@ -54,8 +54,13 @@ import org.elasticsearch.repositories.RepositoriesService;
import org.elasticsearch.snapshots.mockstore.MockRepositoryModule; import org.elasticsearch.snapshots.mockstore.MockRepositoryModule;
import org.junit.Test; import org.junit.Test;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -821,6 +826,48 @@ public class SharedClusterSnapshotRestoreTests extends AbstractSnapshotTests {
assertThrows(client.admin().cluster().prepareGetSnapshots("test-repo").addSnapshots("test-snap-1"), SnapshotMissingException.class); assertThrows(client.admin().cluster().prepareGetSnapshots("test-repo").addSnapshots("test-snap-1"), SnapshotMissingException.class);
} }
@Test
public void deleteSnapshotWithCorruptedSnapshotFileTest() throws Exception {
Client client = client();
Path repo = newTempDirPath();
logger.info("--> creating repository at " + repo.toAbsolutePath());
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("--> truncate snapshot file to make it unreadable");
Path snapshotPath = repo.resolve("snapshot-test-snap-1");
try(SeekableByteChannel outChan = Files.newByteChannel(snapshotPath, StandardOpenOption.WRITE)) {
outChan.truncate(randomInt(10));
}
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);
logger.info("--> make sure that we can create the snapshot again");
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()));
}
@Test @Test
public void snapshotClosedIndexTest() throws Exception { public void snapshotClosedIndexTest() throws Exception {
Client client = client(); Client client = client();