2013-11-08 19:20:43 -05:00
|
|
|
/*
|
2014-01-06 22:48:02 +01:00
|
|
|
* Licensed to Elasticsearch under one or more contributor
|
|
|
|
* license agreements. See the NOTICE file distributed with
|
|
|
|
* this work for additional information regarding copyright
|
|
|
|
* ownership. Elasticsearch licenses this file to you under
|
|
|
|
* the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
* not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2013-11-08 19:20:43 -05:00
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing,
|
|
|
|
* software distributed under the License is distributed on an
|
|
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
* KIND, either express or implied. See the License for the
|
|
|
|
* specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*/
|
|
|
|
package org.elasticsearch.snapshots;
|
|
|
|
|
2014-03-11 17:17:36 -04:00
|
|
|
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
|
2015-12-18 12:43:47 -08:00
|
|
|
import org.elasticsearch.cluster.SnapshotsInProgress;
|
2015-08-17 21:30:13 -04:00
|
|
|
import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
|
2013-11-08 19:20:43 -05:00
|
|
|
import org.elasticsearch.common.settings.Settings;
|
|
|
|
import org.elasticsearch.common.unit.TimeValue;
|
2015-08-22 00:21:13 -07:00
|
|
|
import org.elasticsearch.plugins.Plugin;
|
2013-11-08 19:20:43 -05:00
|
|
|
import org.elasticsearch.repositories.RepositoriesService;
|
2019-07-08 10:55:39 +02:00
|
|
|
import org.elasticsearch.repositories.blobstore.BlobStoreTestUtil;
|
2013-11-08 19:20:43 -05:00
|
|
|
import org.elasticsearch.snapshots.mockstore.MockRepository;
|
2015-08-03 17:43:00 -07:00
|
|
|
import org.elasticsearch.test.ESIntegTestCase;
|
2018-08-30 22:11:23 -04:00
|
|
|
import org.junit.After;
|
2013-11-08 19:20:43 -05:00
|
|
|
|
2014-06-16 16:09:43 +02:00
|
|
|
import java.io.IOException;
|
2014-12-09 05:56:44 -05:00
|
|
|
import java.nio.file.FileVisitResult;
|
|
|
|
import java.nio.file.Files;
|
|
|
|
import java.nio.file.Path;
|
|
|
|
import java.nio.file.SimpleFileVisitor;
|
|
|
|
import java.nio.file.attribute.BasicFileAttributes;
|
2019-03-11 19:27:08 +01:00
|
|
|
import java.util.ArrayList;
|
2016-08-11 11:16:15 -04:00
|
|
|
import java.util.Arrays;
|
2015-08-22 00:21:13 -07:00
|
|
|
import java.util.Collection;
|
2015-06-04 21:22:16 +02:00
|
|
|
import java.util.List;
|
2015-06-01 13:54:31 -10:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2014-12-09 05:56:44 -05:00
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
2013-11-08 19:20:43 -05:00
|
|
|
|
|
|
|
import static org.hamcrest.Matchers.equalTo;
|
|
|
|
|
2015-08-03 17:43:00 -07:00
|
|
|
public abstract class AbstractSnapshotIntegTestCase extends ESIntegTestCase {
|
2013-11-11 09:57:45 +01:00
|
|
|
|
2015-08-10 14:04:45 -07:00
|
|
|
@Override
|
|
|
|
protected Settings nodeSettings(int nodeOrdinal) {
|
2016-04-08 14:59:56 +02:00
|
|
|
return Settings.builder().put(super.nodeSettings(nodeOrdinal))
|
2015-08-18 10:16:40 -07:00
|
|
|
// Rebalancing is causing some checks after restore to randomly fail
|
|
|
|
// due to https://github.com/elastic/elasticsearch/issues/9421
|
2015-11-27 10:25:59 +01:00
|
|
|
.put(EnableAllocationDecider.CLUSTER_ROUTING_REBALANCE_ENABLE_SETTING.getKey(), EnableAllocationDecider.Rebalance.NONE)
|
2015-08-22 00:21:13 -07:00
|
|
|
.build();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Collection<Class<? extends Plugin>> nodePlugins() {
|
2016-08-11 11:16:15 -04:00
|
|
|
return Arrays.asList(MockRepository.Plugin.class);
|
2015-08-10 14:04:45 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 22:11:23 -04:00
|
|
|
@After
|
|
|
|
public void assertConsistentHistoryInLuceneIndex() throws Exception {
|
|
|
|
internalCluster().assertConsistentHistoryBetweenTranslogAndLuceneIndex();
|
|
|
|
}
|
|
|
|
|
2019-07-08 10:55:39 +02:00
|
|
|
private String skipRepoConsistencyCheckReason;
|
|
|
|
|
|
|
|
@After
|
|
|
|
public void assertRepoConsistency() {
|
|
|
|
if (skipRepoConsistencyCheckReason == null) {
|
2019-08-21 17:59:49 +02:00
|
|
|
client().admin().cluster().prepareGetRepositories().get().repositories().forEach(repositoryMetaData -> {
|
|
|
|
final String name = repositoryMetaData.name();
|
|
|
|
if (repositoryMetaData.settings().getAsBoolean("readonly", false) == false) {
|
|
|
|
client().admin().cluster().prepareCleanupRepository(name).get();
|
|
|
|
}
|
|
|
|
BlobStoreTestUtil.assertRepoConsistency(internalCluster(), name);
|
|
|
|
});
|
2019-07-08 10:55:39 +02:00
|
|
|
} else {
|
|
|
|
logger.info("--> skipped repo consistency checks because [{}]", skipRepoConsistencyCheckReason);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void disableRepoConsistencyCheck(String reason) {
|
|
|
|
assertNotNull(reason);
|
|
|
|
skipRepoConsistencyCheckReason = reason;
|
|
|
|
}
|
|
|
|
|
2013-11-08 19:20:43 -05:00
|
|
|
public static long getFailureCount(String repository) {
|
|
|
|
long failureCount = 0;
|
2016-05-27 08:44:20 +02:00
|
|
|
for (RepositoriesService repositoriesService :
|
|
|
|
internalCluster().getDataOrMasterNodeInstances(RepositoriesService.class)) {
|
2013-11-08 19:20:43 -05:00
|
|
|
MockRepository mockRepository = (MockRepository) repositoriesService.repository(repository);
|
|
|
|
failureCount += mockRepository.getFailureCount();
|
|
|
|
}
|
|
|
|
return failureCount;
|
|
|
|
}
|
|
|
|
|
2019-03-11 19:27:08 +01:00
|
|
|
public static void assertFileCount(Path dir, int expectedCount) throws IOException {
|
|
|
|
final List<Path> found = new ArrayList<>();
|
|
|
|
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
|
|
|
|
@Override
|
|
|
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
|
|
|
found.add(file);
|
|
|
|
return FileVisitResult.CONTINUE;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
assertEquals("Unexpected file count, found: [" + found + "].", expectedCount, found.size());
|
|
|
|
}
|
|
|
|
|
2014-12-09 05:56:44 -05:00
|
|
|
public static int numberOfFiles(Path dir) throws IOException {
|
|
|
|
final AtomicInteger count = new AtomicInteger();
|
|
|
|
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
|
|
|
|
@Override
|
|
|
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
|
|
|
count.incrementAndGet();
|
|
|
|
return FileVisitResult.CONTINUE;
|
2013-11-08 19:20:43 -05:00
|
|
|
}
|
2014-12-09 05:56:44 -05:00
|
|
|
});
|
|
|
|
return count.get();
|
2013-11-08 19:20:43 -05:00
|
|
|
}
|
|
|
|
|
2014-06-16 16:09:43 +02:00
|
|
|
public static void stopNode(final String node) throws IOException {
|
2016-02-02 11:32:44 +01:00
|
|
|
internalCluster().stopRandomNode(settings -> settings.get("node.name").equals(node));
|
2013-11-08 19:20:43 -05:00
|
|
|
}
|
|
|
|
|
2013-11-12 13:29:51 -05:00
|
|
|
public void waitForBlock(String node, String repository, TimeValue timeout) throws InterruptedException {
|
2013-11-08 19:20:43 -05:00
|
|
|
long start = System.currentTimeMillis();
|
2014-06-16 14:44:37 +02:00
|
|
|
RepositoriesService repositoriesService = internalCluster().getInstance(RepositoriesService.class, node);
|
2013-11-12 13:29:51 -05:00
|
|
|
MockRepository mockRepository = (MockRepository) repositoriesService.repository(repository);
|
2013-11-08 19:20:43 -05:00
|
|
|
while (System.currentTimeMillis() - start < timeout.millis()) {
|
2013-11-12 13:29:51 -05:00
|
|
|
if (mockRepository.blocked()) {
|
|
|
|
return;
|
2013-11-08 19:20:43 -05:00
|
|
|
}
|
|
|
|
Thread.sleep(100);
|
|
|
|
}
|
2018-06-05 13:00:43 +02:00
|
|
|
fail("Timeout waiting for node [" + node + "] to be blocked");
|
2013-11-08 19:20:43 -05:00
|
|
|
}
|
|
|
|
|
2016-06-02 17:01:14 -04:00
|
|
|
public SnapshotInfo waitForCompletion(String repository, String snapshotName, TimeValue timeout) throws InterruptedException {
|
2013-11-08 19:20:43 -05:00
|
|
|
long start = System.currentTimeMillis();
|
|
|
|
while (System.currentTimeMillis() - start < timeout.millis()) {
|
2018-11-20 12:29:48 -07:00
|
|
|
List<SnapshotInfo> snapshotInfos = client().admin().cluster().prepareGetSnapshots(repository).setSnapshots(snapshotName)
|
|
|
|
.get().getSnapshots();
|
2013-11-08 19:20:43 -05:00
|
|
|
assertThat(snapshotInfos.size(), equalTo(1));
|
|
|
|
if (snapshotInfos.get(0).state().completed()) {
|
2014-03-11 17:17:36 -04:00
|
|
|
// Make sure that snapshot clean up operations are finished
|
|
|
|
ClusterStateResponse stateResponse = client().admin().cluster().prepareState().get();
|
2015-06-10 12:57:45 -04:00
|
|
|
SnapshotsInProgress snapshotsInProgress = stateResponse.getState().custom(SnapshotsInProgress.TYPE);
|
2016-06-02 17:01:14 -04:00
|
|
|
if (snapshotsInProgress == null) {
|
2014-03-11 17:17:36 -04:00
|
|
|
return snapshotInfos.get(0);
|
2016-06-02 17:01:14 -04:00
|
|
|
} else {
|
|
|
|
boolean found = false;
|
|
|
|
for (SnapshotsInProgress.Entry entry : snapshotsInProgress.entries()) {
|
|
|
|
final Snapshot curr = entry.snapshot();
|
|
|
|
if (curr.getRepository().equals(repository) && curr.getSnapshotId().getName().equals(snapshotName)) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (found == false) {
|
|
|
|
return snapshotInfos.get(0);
|
|
|
|
}
|
2014-03-11 17:17:36 -04:00
|
|
|
}
|
2013-11-08 19:20:43 -05:00
|
|
|
}
|
|
|
|
Thread.sleep(100);
|
|
|
|
}
|
|
|
|
fail("Timeout!!!");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2017-07-28 12:28:02 -04:00
|
|
|
public static String blockMasterFromFinalizingSnapshotOnIndexFile(final String repositoryName) {
|
2017-06-02 14:51:13 -04:00
|
|
|
final String masterName = internalCluster().getMasterName();
|
|
|
|
((MockRepository)internalCluster().getInstance(RepositoriesService.class, masterName)
|
|
|
|
.repository(repositoryName)).setBlockOnWriteIndexFile(true);
|
|
|
|
return masterName;
|
|
|
|
}
|
|
|
|
|
2017-07-28 12:28:02 -04:00
|
|
|
public static String blockMasterFromFinalizingSnapshotOnSnapFile(final String repositoryName) {
|
|
|
|
final String masterName = internalCluster().getMasterName();
|
|
|
|
((MockRepository)internalCluster().getInstance(RepositoriesService.class, masterName)
|
|
|
|
.repository(repositoryName)).setBlockAndFailOnWriteSnapFiles(true);
|
|
|
|
return masterName;
|
|
|
|
}
|
|
|
|
|
2016-06-02 17:01:14 -04:00
|
|
|
public static String blockNodeWithIndex(final String repositoryName, final String indexName) {
|
|
|
|
for(String node : internalCluster().nodesInclude(indexName)) {
|
|
|
|
((MockRepository)internalCluster().getInstance(RepositoriesService.class, node).repository(repositoryName))
|
|
|
|
.blockOnDataFiles(true);
|
2013-11-12 13:29:51 -05:00
|
|
|
return node;
|
2013-11-08 19:20:43 -05:00
|
|
|
}
|
2016-06-02 17:01:14 -04:00
|
|
|
fail("No nodes for the index " + indexName + " found");
|
2013-11-12 13:29:51 -05:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2016-03-03 16:12:41 +01:00
|
|
|
public static void blockAllDataNodes(String repository) {
|
|
|
|
for(RepositoriesService repositoriesService : internalCluster().getDataNodeInstances(RepositoriesService.class)) {
|
|
|
|
((MockRepository)repositoriesService.repository(repository)).blockOnDataFiles(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void unblockAllDataNodes(String repository) {
|
|
|
|
for(RepositoriesService repositoriesService : internalCluster().getDataNodeInstances(RepositoriesService.class)) {
|
|
|
|
((MockRepository)repositoriesService.repository(repository)).unblock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-13 14:06:46 +01:00
|
|
|
public void waitForBlockOnAnyDataNode(String repository, TimeValue timeout) throws InterruptedException {
|
2019-09-29 12:21:46 +01:00
|
|
|
final boolean blocked = waitUntil(() -> {
|
|
|
|
for (RepositoriesService repositoriesService : internalCluster().getDataNodeInstances(RepositoriesService.class)) {
|
2016-03-03 16:12:41 +01:00
|
|
|
MockRepository mockRepository = (MockRepository) repositoriesService.repository(repository);
|
2016-03-13 14:06:46 +01:00
|
|
|
if (mockRepository.blocked()) {
|
|
|
|
return true;
|
2016-03-03 16:12:41 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-13 14:06:46 +01:00
|
|
|
return false;
|
2019-09-29 12:21:46 +01:00
|
|
|
}, timeout.millis(), TimeUnit.MILLISECONDS);
|
|
|
|
|
|
|
|
assertTrue("No repository is blocked waiting on a data node", blocked);
|
2016-03-03 16:12:41 +01:00
|
|
|
}
|
|
|
|
|
2016-06-02 17:01:14 -04:00
|
|
|
public static void unblockNode(final String repository, final String node) {
|
|
|
|
((MockRepository)internalCluster().getInstance(RepositoriesService.class, node).repository(repository)).unblock();
|
2013-11-08 19:20:43 -05:00
|
|
|
}
|
|
|
|
}
|