|
|
@@ -8,22 +8,26 @@ package org.elasticsearch.xpack.slm;
|
|
|
|
|
|
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotStatus;
|
|
|
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusResponse;
|
|
|
+import org.elasticsearch.action.search.SearchResponse;
|
|
|
import org.elasticsearch.cluster.ClusterState;
|
|
|
import org.elasticsearch.cluster.SnapshotsInProgress;
|
|
|
+import org.elasticsearch.common.Strings;
|
|
|
import org.elasticsearch.common.settings.Settings;
|
|
|
import org.elasticsearch.common.unit.TimeValue;
|
|
|
+import org.elasticsearch.index.query.QueryBuilders;
|
|
|
import org.elasticsearch.plugins.Plugin;
|
|
|
import org.elasticsearch.repositories.RepositoriesService;
|
|
|
+import org.elasticsearch.snapshots.ConcurrentSnapshotExecutionException;
|
|
|
import org.elasticsearch.snapshots.SnapshotMissingException;
|
|
|
import org.elasticsearch.snapshots.mockstore.MockRepository;
|
|
|
import org.elasticsearch.test.ESIntegTestCase;
|
|
|
import org.elasticsearch.test.junit.annotations.TestLogging;
|
|
|
import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;
|
|
|
-import org.elasticsearch.xpack.core.ilm.LifecycleSettings;
|
|
|
import org.elasticsearch.xpack.core.slm.SnapshotLifecyclePolicy;
|
|
|
import org.elasticsearch.xpack.core.slm.SnapshotLifecyclePolicyItem;
|
|
|
import org.elasticsearch.xpack.core.slm.SnapshotRetentionConfiguration;
|
|
|
import org.elasticsearch.xpack.core.slm.action.ExecuteSnapshotLifecycleAction;
|
|
|
+import org.elasticsearch.xpack.core.slm.action.ExecuteSnapshotRetentionAction;
|
|
|
import org.elasticsearch.xpack.core.slm.action.GetSnapshotLifecycleAction;
|
|
|
import org.elasticsearch.xpack.core.slm.action.PutSnapshotLifecycleAction;
|
|
|
import org.elasticsearch.xpack.ilm.IndexLifecycle;
|
|
|
@@ -50,16 +54,9 @@ public class SLMSnapshotBlockingIntegTests extends ESIntegTestCase {
|
|
|
|
|
|
@After
|
|
|
public void resetSLMSettings() throws Exception {
|
|
|
- // unset retention settings
|
|
|
- client().admin().cluster().prepareUpdateSettings()
|
|
|
- .setTransientSettings(Settings.builder()
|
|
|
- .put(LifecycleSettings.SLM_RETENTION_SCHEDULE, (String) null)
|
|
|
- .build())
|
|
|
- .get();
|
|
|
-
|
|
|
// Cancel/delete all snapshots
|
|
|
assertBusy(() -> {
|
|
|
- logger.info("--> wiping all snapshots");
|
|
|
+ logger.info("--> wiping all snapshots after test");
|
|
|
client().admin().cluster().prepareGetSnapshots(REPO).get().getSnapshots(REPO)
|
|
|
.forEach(snapshotInfo -> {
|
|
|
try {
|
|
|
@@ -124,7 +121,6 @@ public class SLMSnapshotBlockingIntegTests extends ESIntegTestCase {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/46508")
|
|
|
public void testRetentionWhileSnapshotInProgress() throws Exception {
|
|
|
final String indexName = "test";
|
|
|
final String policyId = "slm-policy";
|
|
|
@@ -165,53 +161,74 @@ public class SLMSnapshotBlockingIntegTests extends ESIntegTestCase {
|
|
|
|
|
|
// Take another snapshot, but before doing that, block it from completing
|
|
|
logger.info("--> blocking nodes from completing snapshot");
|
|
|
- blockAllDataNodes(REPO);
|
|
|
- final String secondSnapName = executePolicy(policyId);
|
|
|
-
|
|
|
- // Check that the executed snapshot shows up in the SLM output as in_progress
|
|
|
- assertBusy(() -> {
|
|
|
- GetSnapshotLifecycleAction.Response getResp =
|
|
|
- client().execute(GetSnapshotLifecycleAction.INSTANCE, new GetSnapshotLifecycleAction.Request(policyId)).get();
|
|
|
- logger.info("--> checking for in progress snapshot...");
|
|
|
-
|
|
|
- assertThat(getResp.getPolicies().size(), greaterThan(0));
|
|
|
- SnapshotLifecyclePolicyItem item = getResp.getPolicies().get(0);
|
|
|
- assertNotNull(item.getSnapshotInProgress());
|
|
|
- SnapshotLifecyclePolicyItem.SnapshotInProgress inProgress = item.getSnapshotInProgress();
|
|
|
- assertThat(inProgress.getSnapshotId().getName(), equalTo(secondSnapName));
|
|
|
- assertThat(inProgress.getStartTime(), greaterThan(0L));
|
|
|
- assertThat(inProgress.getState(), anyOf(equalTo(SnapshotsInProgress.State.INIT), equalTo(SnapshotsInProgress.State.STARTED)));
|
|
|
- assertNull(inProgress.getFailure());
|
|
|
- });
|
|
|
-
|
|
|
- // Run retention every second
|
|
|
- client().admin().cluster().prepareUpdateSettings()
|
|
|
- .setTransientSettings(Settings.builder()
|
|
|
- .put(LifecycleSettings.SLM_RETENTION_SCHEDULE, "*/1 * * * * ?")
|
|
|
- .build())
|
|
|
- .get();
|
|
|
- // Guarantee that retention gets a chance to run before unblocking, I know sleeps are not
|
|
|
- // ideal, but we don't currently have a way to force retention to run, so waiting at least
|
|
|
- // a second is the best we can do for now.
|
|
|
- Thread.sleep(1500);
|
|
|
-
|
|
|
- logger.info("--> unblocking snapshots");
|
|
|
- unblockRepo(REPO);
|
|
|
- unblockAllDataNodes(REPO);
|
|
|
-
|
|
|
- // Check that the snapshot created by the policy has been removed by retention
|
|
|
- assertBusy(() -> {
|
|
|
- // Trigger a cluster state update so that it re-checks for a snapshot in progress
|
|
|
- client().admin().cluster().prepareReroute().get();
|
|
|
- logger.info("--> waiting for snapshot to be deleted");
|
|
|
- try {
|
|
|
- SnapshotsStatusResponse s =
|
|
|
- client().admin().cluster().prepareSnapshotStatus(REPO).setSnapshots(completedSnapshotName).get();
|
|
|
- assertNull("expected no snapshot but one was returned", s.getSnapshots().get(0));
|
|
|
- } catch (SnapshotMissingException e) {
|
|
|
- // Great, we wanted it to be deleted!
|
|
|
- }
|
|
|
- });
|
|
|
+ try {
|
|
|
+ blockAllDataNodes(REPO);
|
|
|
+ final String secondSnapName = executePolicy(policyId);
|
|
|
+
|
|
|
+ // Check that the executed snapshot shows up in the SLM output as in_progress
|
|
|
+ assertBusy(() -> {
|
|
|
+ GetSnapshotLifecycleAction.Response getResp =
|
|
|
+ client().execute(GetSnapshotLifecycleAction.INSTANCE, new GetSnapshotLifecycleAction.Request(policyId)).get();
|
|
|
+ logger.info("--> checking for in progress snapshot...");
|
|
|
+
|
|
|
+ assertThat(getResp.getPolicies().size(), greaterThan(0));
|
|
|
+ SnapshotLifecyclePolicyItem item = getResp.getPolicies().get(0);
|
|
|
+ assertNotNull(item.getSnapshotInProgress());
|
|
|
+ SnapshotLifecyclePolicyItem.SnapshotInProgress inProgress = item.getSnapshotInProgress();
|
|
|
+ assertThat(inProgress.getSnapshotId().getName(), equalTo(secondSnapName));
|
|
|
+ assertThat(inProgress.getStartTime(), greaterThan(0L));
|
|
|
+ assertThat(inProgress.getState(), anyOf(equalTo(SnapshotsInProgress.State.INIT),
|
|
|
+ equalTo(SnapshotsInProgress.State.STARTED)));
|
|
|
+ assertNull(inProgress.getFailure());
|
|
|
+ });
|
|
|
+
|
|
|
+ // Run retention
|
|
|
+ logger.info("--> triggering retention");
|
|
|
+ assertTrue(client().execute(ExecuteSnapshotRetentionAction.INSTANCE,
|
|
|
+ new ExecuteSnapshotRetentionAction.Request()).get().isAcknowledged());
|
|
|
+
|
|
|
+ logger.info("--> unblocking snapshots");
|
|
|
+ unblockRepo(REPO);
|
|
|
+ unblockAllDataNodes(REPO);
|
|
|
+
|
|
|
+ // Check that the snapshot created by the policy has been removed by retention
|
|
|
+ assertBusy(() -> {
|
|
|
+ // Trigger a cluster state update so that it re-checks for a snapshot in progress
|
|
|
+ client().admin().cluster().prepareReroute().get();
|
|
|
+ logger.info("--> waiting for snapshot to be deleted");
|
|
|
+ try {
|
|
|
+ SnapshotsStatusResponse s =
|
|
|
+ client().admin().cluster().prepareSnapshotStatus(REPO).setSnapshots(completedSnapshotName).get();
|
|
|
+ assertNull("expected no snapshot but one was returned", s.getSnapshots().get(0));
|
|
|
+ } catch (SnapshotMissingException e) {
|
|
|
+ // Great, we wanted it to be deleted!
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // Cancel the ongoing snapshot to cancel it
|
|
|
+ assertBusy(() -> {
|
|
|
+ try {
|
|
|
+ logger.info("--> cancelling snapshot {}", secondSnapName);
|
|
|
+ client().admin().cluster().prepareDeleteSnapshot(REPO, secondSnapName).get();
|
|
|
+ } catch (ConcurrentSnapshotExecutionException e) {
|
|
|
+ logger.info("--> attempted to stop second snapshot", e);
|
|
|
+ // just wait and retry
|
|
|
+ fail("attempted to stop second snapshot but a snapshot or delete was in progress");
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // Assert that the history document has been written for taking the snapshot and deleting it
|
|
|
+ assertBusy(() -> {
|
|
|
+ SearchResponse resp = client().prepareSearch(".slm-history*")
|
|
|
+ .setQuery(QueryBuilders.matchQuery("snapshot_name", completedSnapshotName)).get();
|
|
|
+ logger.info("--> checking history written for {}, got: {}",
|
|
|
+ completedSnapshotName, Strings.arrayToCommaDelimitedString(resp.getHits().getHits()));
|
|
|
+ assertThat(resp.getHits().getTotalHits().value, equalTo(2L));
|
|
|
+ });
|
|
|
+ } finally {
|
|
|
+ unblockRepo(REPO);
|
|
|
+ unblockAllDataNodes(REPO);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private void initializeRepo(String repoName) {
|