Skip to content

Separate SLM stop/start/status API from ILM #47710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

package org.elasticsearch.xpack.core.slm.action;

import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.xpack.core.ilm.OperationMode;

import java.io.IOException;

public class GetSLMStatusAction extends ActionType<GetSLMStatusAction.Response> {
public static final GetSLMStatusAction INSTANCE = new GetSLMStatusAction();
public static final String NAME = "cluster:admin/slm/status";

protected GetSLMStatusAction() {
super(NAME, GetSLMStatusAction.Response::new);
}

public static class Response extends ActionResponse implements ToXContentObject {

private OperationMode mode;

public Response(StreamInput in) throws IOException {
super(in);
this.mode = in.readEnum(OperationMode.class);
}

public Response(OperationMode mode) {
this.mode = mode;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeEnum(this.mode);
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field("operation_mode", this.mode);
builder.endObject();
return builder;
}
}

public static class Request extends AcknowledgedRequest<GetSLMStatusAction.Request> {

public Request(StreamInput in) throws IOException {
super(in);
}

public Request() {
}

@Override
public ActionRequestValidationException validate() {
return null;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

package org.elasticsearch.xpack.core.slm.action;

import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.common.io.stream.StreamInput;

import java.io.IOException;

public class StartSLMAction extends ActionType<AcknowledgedResponse> {
public static final StartSLMAction INSTANCE = new StartSLMAction();
public static final String NAME = "cluster:admin/slm/start";

protected StartSLMAction() {
super(NAME, AcknowledgedResponse::new);
}

public static class Request extends AcknowledgedRequest<StartSLMAction.Request> {

public Request(StreamInput in) throws IOException {
super(in);
}

public Request() {
}

@Override
public ActionRequestValidationException validate() {
return null;
}

@Override
public int hashCode() {
return 86;
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj.getClass() != getClass()) {
return false;
}
return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

package org.elasticsearch.xpack.core.slm.action;

import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.common.io.stream.StreamInput;

import java.io.IOException;

public class StopSLMAction extends ActionType<AcknowledgedResponse> {
public static final StopSLMAction INSTANCE = new StopSLMAction();
public static final String NAME = "cluster:admin/slm/stop";

protected StopSLMAction() {
super(NAME, AcknowledgedResponse::new);
}

public static class Request extends AcknowledgedRequest<Request> {

public Request(StreamInput in) throws IOException {
super(in);
}

public Request() {
}

@Override
public ActionRequestValidationException validate() {
return null;
}

@Override
public int hashCode() {
return 85;
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj.getClass() != getClass()) {
return false;
}
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,98 @@ public void testPolicyManualExecution() throws Exception {
});
}


@SuppressWarnings("unchecked")
public void testStartStopStatus() throws Exception {
final String indexName = "test";
final String policyName = "start-stop-policy";
final String repoId = "start-stop-repo";
int docCount = randomIntBetween(10, 50);
for (int i = 0; i < docCount; i++) {
index(client(), indexName, "" + i, "foo", "bar");
}

// Create a snapshot repo
initializeRepo(repoId);

// Stop SLM so nothing happens
client().performRequest(new Request("POST", "/_slm/stop"));

assertBusy(() -> {
logger.info("--> waiting for SLM to stop");
assertThat(EntityUtils.toString(client().performRequest(new Request("GET", "/_slm/status")).getEntity()),
containsString("STOPPED"));
});

try {
createSnapshotPolicy(policyName, "snap", "*/1 * * * * ?", repoId, indexName, true,
new SnapshotRetentionConfiguration(TimeValue.ZERO, null, null));
long start = System.currentTimeMillis();
final String snapshotName = executePolicy(policyName);

// Check that the executed snapshot is created
assertBusy(() -> {
try {
logger.info("--> checking for snapshot creation...");
Response response = client().performRequest(new Request("GET", "/_snapshot/" + repoId + "/" + snapshotName));
Map<String, Object> snapshotResponseMap;
try (InputStream is = response.getEntity().getContent()) {
snapshotResponseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), is, true);
}
assertThat(snapshotResponseMap.size(), greaterThan(0));
final Map<String, Object> metadata = extractMetadata(snapshotResponseMap, snapshotName);
assertNotNull(metadata);
assertThat(metadata.get("policy"), equalTo(policyName));
assertHistoryIsPresent(policyName, true, repoId, CREATE_OPERATION);
} catch (ResponseException e) {
fail("expected snapshot to exist but it does not: " + EntityUtils.toString(e.getResponse().getEntity()));
}
});

// Sleep for up to a second, but at least 1 second since we scheduled the policy so we can
// ensure it *would* have run if SLM were running
Thread.sleep(Math.min(0, TimeValue.timeValueSeconds(1).millis() - Math.min(0, System.currentTimeMillis() - start)));

client().performRequest(new Request("POST", "/_slm/_execute_retention"));

// Retention and the manually executed policy should still have run,
// but only the one we manually ran.
assertBusy(() -> {
logger.info("--> checking for stats updates...");
Map<String, Object> stats = getSLMStats();
Map<String, Object> policyStats = policyStatsAsMap(stats);
Map<String, Object> policyIdStats = (Map<String, Object>) policyStats.get(policyName);
int snapsTaken = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_TAKEN.getPreferredName());
int totalTaken = (int) stats.get(SnapshotLifecycleStats.TOTAL_TAKEN.getPreferredName());
int totalFailed = (int) stats.get(SnapshotLifecycleStats.TOTAL_FAILED.getPreferredName());
int totalDeleted = (int) stats.get(SnapshotLifecycleStats.TOTAL_DELETIONS.getPreferredName());
assertThat(snapsTaken, equalTo(1));
assertThat(totalTaken, equalTo(1));
assertThat(totalDeleted, equalTo(1));
assertThat(totalFailed, equalTo(0));
});

assertBusy(() -> {
try {
Map<String, List<Map<?, ?>>> snaps = wipeSnapshots();
logger.info("--> checking for wiped snapshots: {}", snaps);
assertThat(snaps.size(), equalTo(0));
} catch (ResponseException e) {
logger.error("got exception wiping snapshots", e);
fail("got exception: " + EntityUtils.toString(e.getResponse().getEntity()));
}
});
} finally {
client().performRequest(new Request("POST", "/_slm/start"));

assertBusy(() -> {
logger.info("--> waiting for SLM to start");
assertThat(EntityUtils.toString(client().performRequest(new Request("GET", "/_slm/status")).getEntity()),
containsString("RUNNING"));
});
}
}

@SuppressWarnings("unchecked")
public void testBasicTimeBasedRetenion() throws Exception {
final String indexName = "test";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,12 @@
import org.elasticsearch.xpack.core.slm.action.DeleteSnapshotLifecycleAction;
import org.elasticsearch.xpack.core.slm.action.ExecuteSnapshotLifecycleAction;
import org.elasticsearch.xpack.core.slm.action.ExecuteSnapshotRetentionAction;
import org.elasticsearch.xpack.core.slm.action.GetSLMStatusAction;
import org.elasticsearch.xpack.core.slm.action.GetSnapshotLifecycleAction;
import org.elasticsearch.xpack.core.slm.action.GetSnapshotLifecycleStatsAction;
import org.elasticsearch.xpack.core.slm.action.PutSnapshotLifecycleAction;
import org.elasticsearch.xpack.core.slm.action.StartSLMAction;
import org.elasticsearch.xpack.core.slm.action.StopSLMAction;
import org.elasticsearch.xpack.core.slm.history.SnapshotHistoryStore;
import org.elasticsearch.xpack.core.slm.history.SnapshotLifecycleTemplateRegistry;
import org.elasticsearch.xpack.ilm.action.RestDeleteLifecycleAction;
Expand Down Expand Up @@ -98,15 +101,21 @@
import org.elasticsearch.xpack.slm.action.RestDeleteSnapshotLifecycleAction;
import org.elasticsearch.xpack.slm.action.RestExecuteSnapshotLifecycleAction;
import org.elasticsearch.xpack.slm.action.RestExecuteSnapshotRetentionAction;
import org.elasticsearch.xpack.slm.action.RestGetSLMStatusAction;
import org.elasticsearch.xpack.slm.action.RestGetSnapshotLifecycleAction;
import org.elasticsearch.xpack.slm.action.RestGetSnapshotLifecycleStatsAction;
import org.elasticsearch.xpack.slm.action.RestPutSnapshotLifecycleAction;
import org.elasticsearch.xpack.slm.action.RestStartSLMAction;
import org.elasticsearch.xpack.slm.action.RestStopSLMAction;
import org.elasticsearch.xpack.slm.action.TransportDeleteSnapshotLifecycleAction;
import org.elasticsearch.xpack.slm.action.TransportExecuteSnapshotLifecycleAction;
import org.elasticsearch.xpack.slm.action.TransportExecuteSnapshotRetentionAction;
import org.elasticsearch.xpack.slm.action.TransportGetSLMStatusAction;
import org.elasticsearch.xpack.slm.action.TransportGetSnapshotLifecycleAction;
import org.elasticsearch.xpack.slm.action.TransportGetSnapshotLifecycleStatsAction;
import org.elasticsearch.xpack.slm.action.TransportPutSnapshotLifecycleAction;
import org.elasticsearch.xpack.slm.action.TransportStartSLMAction;
import org.elasticsearch.xpack.slm.action.TransportStopSLMAction;

import java.io.IOException;
import java.time.Clock;
Expand Down Expand Up @@ -234,7 +243,10 @@ public List<RestHandler> getRestHandlers(Settings settings, RestController restC
new RestGetSnapshotLifecycleAction(restController),
new RestExecuteSnapshotLifecycleAction(restController),
new RestGetSnapshotLifecycleStatsAction(restController),
new RestExecuteSnapshotRetentionAction(restController)
new RestExecuteSnapshotRetentionAction(restController),
new RestStopSLMAction(restController),
new RestStartSLMAction(restController),
new RestGetSLMStatusAction(restController)
));
}
return handlers;
Expand Down Expand Up @@ -270,7 +282,10 @@ public List<RestHandler> getRestHandlers(Settings settings, RestController restC
new ActionHandler<>(GetSnapshotLifecycleAction.INSTANCE, TransportGetSnapshotLifecycleAction.class),
new ActionHandler<>(ExecuteSnapshotLifecycleAction.INSTANCE, TransportExecuteSnapshotLifecycleAction.class),
new ActionHandler<>(GetSnapshotLifecycleStatsAction.INSTANCE, TransportGetSnapshotLifecycleStatsAction.class),
new ActionHandler<>(ExecuteSnapshotRetentionAction.INSTANCE, TransportExecuteSnapshotRetentionAction.class)
new ActionHandler<>(ExecuteSnapshotRetentionAction.INSTANCE, TransportExecuteSnapshotRetentionAction.class),
new ActionHandler<>(StartSLMAction.INSTANCE, TransportStartSLMAction.class),
new ActionHandler<>(StopSLMAction.INSTANCE, TransportStopSLMAction.class),
new ActionHandler<>(GetSLMStatusAction.INSTANCE, TransportGetSLMStatusAction.class)
));
}
return actions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,7 @@ assert isClusterServiceStoppedOrClosed() : "close is called by closing the plugi
}

public void submitOperationModeUpdate(OperationMode mode) {
clusterService.submitStateUpdateTask("ilm_operation_mode_update",
new OperationModeUpdateTask(mode));
clusterService.submitStateUpdateTask("ilm_operation_mode_update", OperationModeUpdateTask.ilmMode(mode));
}

/**
Expand Down
Loading