Include in-progress snapshot for a policy with get SLM policy… (#45245)
This commit adds the "in_progress" key to the SLM get policy API, returning a policy that looks like: ```json { "daily-snapshots" : { "version" : 1, "modified_date" : "2019-08-05T18:41:48.778Z", "modified_date_millis" : 1565030508778, "policy" : { "name" : "<production-snap-{now/d}>", "schedule" : "0 30 1 * * ?", "repository" : "repo", "config" : { "indices" : [ "foo-*", "important" ], "ignore_unavailable" : true, "include_global_state" : false }, "retention" : { "expire_after" : "10m" } }, "last_success" : { "snapshot_name" : "production-snap-2019.08.05-oxctmnobqye3luim4uejhg", "time_string" : "2019-08-05T18:42:23.257Z", "time" : 1565030543257 }, "next_execution" : "2019-08-06T01:30:00.000Z", "next_execution_millis" : 1565055000000, "in_progress" : { "name" : "production-snap-2019.08.05-oxctmnobqye3luim4uejhg", "uuid" : "t8Idqt6JQxiZrzp0Vt7z6g", "state" : "STARTED", "start_time" : "2019-08-05T18:42:22.998Z", "start_time_millis" : 1565030542998 } } } ``` These are only visible while the snapshot is being taken (or failed), since it reads from the cluster state rather than from the repository itself.
This commit is contained in:
parent
9384774b4c
commit
c7ec0b8431
|
@ -21,10 +21,12 @@ package org.elasticsearch.client.slm;
|
|||
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.snapshots.SnapshotId;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
@ -39,6 +41,7 @@ public class SnapshotLifecyclePolicyMetadata implements ToXContentObject {
|
|||
static final ParseField LAST_FAILURE = new ParseField("last_failure");
|
||||
static final ParseField NEXT_EXECUTION_MILLIS = new ParseField("next_execution_millis");
|
||||
static final ParseField NEXT_EXECUTION = new ParseField("next_execution");
|
||||
static final ParseField SNAPSHOT_IN_PROGRESS = new ParseField("in_progress");
|
||||
|
||||
private final SnapshotLifecyclePolicy policy;
|
||||
private final long version;
|
||||
|
@ -48,6 +51,8 @@ public class SnapshotLifecyclePolicyMetadata implements ToXContentObject {
|
|||
private final SnapshotInvocationRecord lastSuccess;
|
||||
@Nullable
|
||||
private final SnapshotInvocationRecord lastFailure;
|
||||
@Nullable
|
||||
private final SnapshotInProgress snapshotInProgress;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final ConstructingObjectParser<SnapshotLifecyclePolicyMetadata, String> PARSER =
|
||||
|
@ -59,8 +64,9 @@ public class SnapshotLifecyclePolicyMetadata implements ToXContentObject {
|
|||
SnapshotInvocationRecord lastSuccess = (SnapshotInvocationRecord) a[3];
|
||||
SnapshotInvocationRecord lastFailure = (SnapshotInvocationRecord) a[4];
|
||||
long nextExecution = (long) a[5];
|
||||
SnapshotInProgress sip = (SnapshotInProgress) a[6];
|
||||
|
||||
return new SnapshotLifecyclePolicyMetadata(policy, version, modifiedDate, lastSuccess, lastFailure, nextExecution);
|
||||
return new SnapshotLifecyclePolicyMetadata(policy, version, modifiedDate, lastSuccess, lastFailure, nextExecution, sip);
|
||||
});
|
||||
|
||||
static {
|
||||
|
@ -70,6 +76,7 @@ public class SnapshotLifecyclePolicyMetadata implements ToXContentObject {
|
|||
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SnapshotInvocationRecord::parse, LAST_SUCCESS);
|
||||
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SnapshotInvocationRecord::parse, LAST_FAILURE);
|
||||
PARSER.declareLong(ConstructingObjectParser.constructorArg(), NEXT_EXECUTION_MILLIS);
|
||||
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SnapshotInProgress::parse, SNAPSHOT_IN_PROGRESS);
|
||||
}
|
||||
|
||||
public static SnapshotLifecyclePolicyMetadata parse(XContentParser parser, String id) {
|
||||
|
@ -78,13 +85,15 @@ public class SnapshotLifecyclePolicyMetadata implements ToXContentObject {
|
|||
|
||||
public SnapshotLifecyclePolicyMetadata(SnapshotLifecyclePolicy policy, long version, long modifiedDate,
|
||||
SnapshotInvocationRecord lastSuccess, SnapshotInvocationRecord lastFailure,
|
||||
long nextExecution) {
|
||||
long nextExecution,
|
||||
@Nullable SnapshotInProgress snapshotInProgress) {
|
||||
this.policy = policy;
|
||||
this.version = version;
|
||||
this.modifiedDate = modifiedDate;
|
||||
this.lastSuccess = lastSuccess;
|
||||
this.lastFailure = lastFailure;
|
||||
this.nextExecution = nextExecution;
|
||||
this.snapshotInProgress = snapshotInProgress;
|
||||
}
|
||||
|
||||
public SnapshotLifecyclePolicy getPolicy() {
|
||||
|
@ -115,6 +124,11 @@ public class SnapshotLifecyclePolicyMetadata implements ToXContentObject {
|
|||
return this.nextExecution;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SnapshotInProgress getSnapshotInProgress() {
|
||||
return this.snapshotInProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
|
@ -128,6 +142,9 @@ public class SnapshotLifecyclePolicyMetadata implements ToXContentObject {
|
|||
builder.field(LAST_FAILURE.getPreferredName(), lastFailure);
|
||||
}
|
||||
builder.timeField(NEXT_EXECUTION_MILLIS.getPreferredName(), NEXT_EXECUTION.getPreferredName(), nextExecution);
|
||||
if (snapshotInProgress != null) {
|
||||
builder.field(SNAPSHOT_IN_PROGRESS.getPreferredName(), snapshotInProgress);
|
||||
}
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
@ -154,4 +171,84 @@ public class SnapshotLifecyclePolicyMetadata implements ToXContentObject {
|
|||
Objects.equals(nextExecution, other.nextExecution);
|
||||
}
|
||||
|
||||
public static class SnapshotInProgress implements ToXContentObject {
|
||||
private static final ParseField NAME = new ParseField("name");
|
||||
private static final ParseField UUID = new ParseField("uuid");
|
||||
private static final ParseField STATE = new ParseField("state");
|
||||
private static final ParseField START_TIME = new ParseField("start_time_millis");
|
||||
private static final ParseField FAILURE = new ParseField("failure");
|
||||
|
||||
private static final ConstructingObjectParser<SnapshotInProgress, Void> PARSER =
|
||||
new ConstructingObjectParser<>("snapshot_in_progress", true, a -> {
|
||||
SnapshotId id = new SnapshotId((String) a[0], (String) a[1]);
|
||||
String state = (String) a[2];
|
||||
long start = (long) a[3];
|
||||
String failure = (String) a[4];
|
||||
return new SnapshotInProgress(id, state, start, failure);
|
||||
});
|
||||
|
||||
static {
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), UUID);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), STATE);
|
||||
PARSER.declareLong(ConstructingObjectParser.constructorArg(), START_TIME);
|
||||
PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), FAILURE);
|
||||
}
|
||||
|
||||
private final SnapshotId snapshotId;
|
||||
private final String state;
|
||||
private final long startTime;
|
||||
private final String failure;
|
||||
|
||||
public SnapshotInProgress(SnapshotId snapshotId, String state, long startTime, @Nullable String failure) {
|
||||
this.snapshotId = snapshotId;
|
||||
this.state = state;
|
||||
this.startTime = startTime;
|
||||
this.failure = failure;
|
||||
}
|
||||
|
||||
private static SnapshotInProgress parse(XContentParser parser, String name) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(NAME.getPreferredName(), snapshotId.getName());
|
||||
builder.field(UUID.getPreferredName(), snapshotId.getUUID());
|
||||
builder.field(STATE.getPreferredName(), state);
|
||||
builder.timeField(START_TIME.getPreferredName(), "start_time", startTime);
|
||||
if (failure != null) {
|
||||
builder.field(FAILURE.getPreferredName(), failure);
|
||||
}
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(snapshotId, state, startTime, failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
SnapshotInProgress other = (SnapshotInProgress) obj;
|
||||
return Objects.equals(snapshotId, other.snapshotId) &&
|
||||
Objects.equals(state, other.state) &&
|
||||
startTime == other.startTime &&
|
||||
Objects.equals(failure, other.failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Strings.toString(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -854,6 +854,8 @@ public class ILMDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
long nextPolicyExecutionDate = policyMeta.getNextExecution();
|
||||
SnapshotInvocationRecord lastSuccess = policyMeta.getLastSuccess();
|
||||
SnapshotInvocationRecord lastFailure = policyMeta.getLastFailure();
|
||||
SnapshotLifecyclePolicyMetadata.SnapshotInProgress inProgress =
|
||||
policyMeta.getSnapshotInProgress();
|
||||
SnapshotLifecyclePolicy retrievedPolicy = policyMeta.getPolicy(); // <2>
|
||||
String id = retrievedPolicy.getId();
|
||||
String snapshotNameFormat = retrievedPolicy.getName();
|
||||
|
|
|
@ -47,6 +47,8 @@ import static org.elasticsearch.cluster.metadata.MetaDataCreateIndexService.MAX_
|
|||
public class SnapshotLifecyclePolicy extends AbstractDiffable<SnapshotLifecyclePolicy>
|
||||
implements Writeable, Diffable<SnapshotLifecyclePolicy>, ToXContentObject {
|
||||
|
||||
public static final String POLICY_ID_METADATA_FIELD = "policy";
|
||||
|
||||
private final String id;
|
||||
private final String name;
|
||||
private final String schedule;
|
||||
|
@ -59,7 +61,6 @@ public class SnapshotLifecyclePolicy extends AbstractDiffable<SnapshotLifecycleP
|
|||
private static final ParseField CONFIG = new ParseField("config");
|
||||
private static final IndexNameExpressionResolver.DateMathExpressionResolver DATE_MATH_RESOLVER =
|
||||
new IndexNameExpressionResolver.DateMathExpressionResolver();
|
||||
private static final String POLICY_ID_METADATA_FIELD = "policy";
|
||||
private static final String METADATA_FIELD_NAME = "metadata";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -6,13 +6,17 @@
|
|||
|
||||
package org.elasticsearch.xpack.core.slm;
|
||||
|
||||
import org.elasticsearch.cluster.SnapshotsInProgress;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ToXContentFragment;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.snapshots.SnapshotId;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
@ -24,21 +28,27 @@ import java.util.Objects;
|
|||
*/
|
||||
public class SnapshotLifecyclePolicyItem implements ToXContentFragment, Writeable {
|
||||
|
||||
private static final ParseField SNAPSHOT_IN_PROGRESS = new ParseField("in_progress");
|
||||
|
||||
private final SnapshotLifecyclePolicy policy;
|
||||
private final long version;
|
||||
private final long modifiedDate;
|
||||
@Nullable
|
||||
private final SnapshotInProgress snapshotInProgress;
|
||||
|
||||
@Nullable
|
||||
private final SnapshotInvocationRecord lastSuccess;
|
||||
|
||||
@Nullable
|
||||
private final SnapshotInvocationRecord lastFailure;
|
||||
public SnapshotLifecyclePolicyItem(SnapshotLifecyclePolicyMetadata policyMetadata) {
|
||||
public SnapshotLifecyclePolicyItem(SnapshotLifecyclePolicyMetadata policyMetadata,
|
||||
@Nullable SnapshotInProgress snapshotInProgress) {
|
||||
this.policy = policyMetadata.getPolicy();
|
||||
this.version = policyMetadata.getVersion();
|
||||
this.modifiedDate = policyMetadata.getModifiedDate();
|
||||
this.lastSuccess = policyMetadata.getLastSuccess();
|
||||
this.lastFailure = policyMetadata.getLastFailure();
|
||||
this.snapshotInProgress = snapshotInProgress;
|
||||
}
|
||||
|
||||
public SnapshotLifecyclePolicyItem(StreamInput in) throws IOException {
|
||||
|
@ -47,17 +57,20 @@ public class SnapshotLifecyclePolicyItem implements ToXContentFragment, Writeabl
|
|||
this.modifiedDate = in.readVLong();
|
||||
this.lastSuccess = in.readOptionalWriteable(SnapshotInvocationRecord::new);
|
||||
this.lastFailure = in.readOptionalWriteable(SnapshotInvocationRecord::new);
|
||||
this.snapshotInProgress = in.readOptionalWriteable(SnapshotInProgress::new);
|
||||
}
|
||||
|
||||
// For testing
|
||||
|
||||
SnapshotLifecyclePolicyItem(SnapshotLifecyclePolicy policy, long version, long modifiedDate,
|
||||
SnapshotInvocationRecord lastSuccess, SnapshotInvocationRecord lastFailure) {
|
||||
SnapshotInvocationRecord lastSuccess, SnapshotInvocationRecord lastFailure,
|
||||
@Nullable SnapshotInProgress snapshotInProgress) {
|
||||
this.policy = policy;
|
||||
this.version = version;
|
||||
this.modifiedDate = modifiedDate;
|
||||
this.lastSuccess = lastSuccess;
|
||||
this.lastFailure = lastFailure;
|
||||
this.snapshotInProgress = snapshotInProgress;
|
||||
}
|
||||
public SnapshotLifecyclePolicy getPolicy() {
|
||||
return policy;
|
||||
|
@ -79,6 +92,11 @@ public class SnapshotLifecyclePolicyItem implements ToXContentFragment, Writeabl
|
|||
return lastFailure;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SnapshotInProgress getSnapshotInProgress() {
|
||||
return this.snapshotInProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
policy.writeTo(out);
|
||||
|
@ -86,6 +104,7 @@ public class SnapshotLifecyclePolicyItem implements ToXContentFragment, Writeabl
|
|||
out.writeVLong(modifiedDate);
|
||||
out.writeOptionalWriteable(lastSuccess);
|
||||
out.writeOptionalWriteable(lastFailure);
|
||||
out.writeOptionalWriteable(snapshotInProgress);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -106,7 +125,8 @@ public class SnapshotLifecyclePolicyItem implements ToXContentFragment, Writeabl
|
|||
version == other.version &&
|
||||
modifiedDate == other.modifiedDate &&
|
||||
Objects.equals(lastSuccess, other.lastSuccess) &&
|
||||
Objects.equals(lastFailure, other.lastFailure);
|
||||
Objects.equals(lastFailure, other.lastFailure) &&
|
||||
Objects.equals(snapshotInProgress, other.snapshotInProgress);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,6 +144,9 @@ public class SnapshotLifecyclePolicyItem implements ToXContentFragment, Writeabl
|
|||
}
|
||||
builder.timeField(SnapshotLifecyclePolicyMetadata.NEXT_EXECUTION_MILLIS.getPreferredName(),
|
||||
SnapshotLifecyclePolicyMetadata.NEXT_EXECUTION.getPreferredName(), policy.calculateNextExecution());
|
||||
if (snapshotInProgress != null) {
|
||||
builder.field(SNAPSHOT_IN_PROGRESS.getPreferredName(), snapshotInProgress);
|
||||
}
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
@ -132,4 +155,84 @@ public class SnapshotLifecyclePolicyItem implements ToXContentFragment, Writeabl
|
|||
public String toString() {
|
||||
return Strings.toString(this);
|
||||
}
|
||||
|
||||
public static class SnapshotInProgress implements ToXContentObject, Writeable {
|
||||
private static final ParseField NAME = new ParseField("name");
|
||||
private static final ParseField UUID = new ParseField("uuid");
|
||||
private static final ParseField STATE = new ParseField("state");
|
||||
private static final ParseField START_TIME = new ParseField("start_time_millis");
|
||||
private static final ParseField FAILURE = new ParseField("failure");
|
||||
|
||||
private final SnapshotId snapshotId;
|
||||
private final SnapshotsInProgress.State state;
|
||||
private final long startTime;
|
||||
private final String failure;
|
||||
|
||||
public SnapshotInProgress(SnapshotId snapshotId, SnapshotsInProgress.State state, long startTime, @Nullable String failure) {
|
||||
this.snapshotId = snapshotId;
|
||||
this.state = state;
|
||||
this.startTime = startTime;
|
||||
this.failure = failure;
|
||||
}
|
||||
|
||||
SnapshotInProgress(StreamInput in) throws IOException {
|
||||
this.snapshotId = new SnapshotId(in);
|
||||
this.state = in.readEnum(SnapshotsInProgress.State.class);
|
||||
this.startTime = in.readVLong();
|
||||
this.failure = in.readOptionalString();
|
||||
}
|
||||
|
||||
public static SnapshotInProgress fromEntry(SnapshotsInProgress.Entry entry) {
|
||||
return new SnapshotInProgress(entry.snapshot().getSnapshotId(),
|
||||
entry.state(), entry.startTime(), entry.failure());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
this.snapshotId.writeTo(out);
|
||||
out.writeEnum(this.state);
|
||||
out.writeVLong(this.startTime);
|
||||
out.writeOptionalString(this.failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(NAME.getPreferredName(), snapshotId.getName());
|
||||
builder.field(UUID.getPreferredName(), snapshotId.getUUID());
|
||||
builder.field(STATE.getPreferredName(), state);
|
||||
builder.timeField(START_TIME.getPreferredName(), "start_time", startTime);
|
||||
if (failure != null) {
|
||||
builder.field(FAILURE.getPreferredName(), failure);
|
||||
}
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(snapshotId, state, startTime, failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
SnapshotInProgress other = (SnapshotInProgress) obj;
|
||||
return Objects.equals(snapshotId, other.snapshotId) &&
|
||||
Objects.equals(state, other.state) &&
|
||||
startTime == other.startTime &&
|
||||
Objects.equals(failure, other.failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Strings.toString(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
package org.elasticsearch.xpack.core.slm;
|
||||
|
||||
import org.elasticsearch.cluster.SnapshotsInProgress;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.snapshots.SnapshotId;
|
||||
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
|
@ -15,47 +17,68 @@ import static org.elasticsearch.xpack.core.slm.SnapshotLifecyclePolicyMetadataTe
|
|||
|
||||
public class SnapshotLifecyclePolicyItemTests extends AbstractWireSerializingTestCase<SnapshotLifecyclePolicyItem> {
|
||||
|
||||
public static SnapshotLifecyclePolicyItem.SnapshotInProgress randomSnapshotInProgress() {
|
||||
return rarely() ? null : new SnapshotLifecyclePolicyItem.SnapshotInProgress(
|
||||
new SnapshotId("name-" + randomAlphaOfLength(3), "uuid-" + randomAlphaOfLength(3)),
|
||||
randomFrom(SnapshotsInProgress.State.values()),
|
||||
randomNonNegativeLong(),
|
||||
randomBoolean() ? null : "failure!");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SnapshotLifecyclePolicyItem createTestInstance() {
|
||||
return new SnapshotLifecyclePolicyItem(createRandomPolicyMetadata(randomAlphaOfLengthBetween(5, 10)));
|
||||
return new SnapshotLifecyclePolicyItem(createRandomPolicyMetadata(randomAlphaOfLengthBetween(5, 10)), randomSnapshotInProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SnapshotLifecyclePolicyItem mutateInstance(SnapshotLifecyclePolicyItem instance) {
|
||||
switch (between(0, 4)) {
|
||||
switch (between(0, 5)) {
|
||||
case 0:
|
||||
String newPolicyId = randomValueOtherThan(instance.getPolicy().getId(), () -> randomAlphaOfLengthBetween(5, 10));
|
||||
return new SnapshotLifecyclePolicyItem(createRandomPolicy(newPolicyId),
|
||||
instance.getVersion(),
|
||||
instance.getModifiedDate(),
|
||||
instance.getLastSuccess(),
|
||||
instance.getLastFailure());
|
||||
instance.getLastFailure(),
|
||||
instance.getSnapshotInProgress());
|
||||
case 1:
|
||||
return new SnapshotLifecyclePolicyItem(instance.getPolicy(),
|
||||
randomValueOtherThan(instance.getVersion(), ESTestCase::randomNonNegativeLong),
|
||||
instance.getModifiedDate(),
|
||||
instance.getLastSuccess(),
|
||||
instance.getLastFailure());
|
||||
instance.getLastFailure(),
|
||||
instance.getSnapshotInProgress());
|
||||
case 2:
|
||||
return new SnapshotLifecyclePolicyItem(instance.getPolicy(),
|
||||
instance.getVersion(),
|
||||
randomValueOtherThan(instance.getModifiedDate(), ESTestCase::randomNonNegativeLong),
|
||||
instance.getLastSuccess(),
|
||||
instance.getLastFailure());
|
||||
instance.getLastFailure(),
|
||||
instance.getSnapshotInProgress());
|
||||
case 3:
|
||||
return new SnapshotLifecyclePolicyItem(instance.getPolicy(),
|
||||
instance.getVersion(),
|
||||
instance.getModifiedDate(),
|
||||
randomValueOtherThan(instance.getLastSuccess(),
|
||||
SnapshotInvocationRecordTests::randomSnapshotInvocationRecord),
|
||||
instance.getLastFailure());
|
||||
instance.getLastFailure(),
|
||||
instance.getSnapshotInProgress());
|
||||
case 4:
|
||||
return new SnapshotLifecyclePolicyItem(instance.getPolicy(),
|
||||
instance.getVersion(),
|
||||
instance.getModifiedDate(),
|
||||
instance.getLastSuccess(),
|
||||
randomValueOtherThan(instance.getLastFailure(),
|
||||
SnapshotInvocationRecordTests::randomSnapshotInvocationRecord));
|
||||
SnapshotInvocationRecordTests::randomSnapshotInvocationRecord),
|
||||
instance.getSnapshotInProgress());
|
||||
case 5:
|
||||
return new SnapshotLifecyclePolicyItem(instance.getPolicy(),
|
||||
instance.getVersion(),
|
||||
instance.getModifiedDate(),
|
||||
instance.getLastSuccess(),
|
||||
instance.getLastFailure(),
|
||||
randomValueOtherThan(instance.getSnapshotInProgress(),
|
||||
SnapshotLifecyclePolicyItemTests::randomSnapshotInProgress));
|
||||
default:
|
||||
throw new AssertionError("failure, got illegal switch case");
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -168,7 +169,6 @@ public class SnapshotLifecycleIT extends ESRestTestCase {
|
|||
final String policyName = "test-policy";
|
||||
final String repoId = "my-repo";
|
||||
int docCount = randomIntBetween(10, 50);
|
||||
List<IndexRequestBuilder> indexReqs = new ArrayList<>();
|
||||
for (int i = 0; i < docCount; i++) {
|
||||
index(client(), indexName, "" + i, "foo", "bar");
|
||||
}
|
||||
|
@ -218,6 +218,68 @@ public class SnapshotLifecycleIT extends ESRestTestCase {
|
|||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testSnapshotInProgress() throws Exception {
|
||||
final String indexName = "test";
|
||||
final String policyName = "test-policy";
|
||||
final String repoId = "my-repo";
|
||||
int docCount = 20;
|
||||
for (int i = 0; i < docCount; i++) {
|
||||
index(client(), indexName, "" + i, "foo", "bar");
|
||||
}
|
||||
|
||||
// Create a snapshot repo
|
||||
inializeRepo(repoId, 1);
|
||||
|
||||
createSnapshotPolicy(policyName, "snap", "1 2 3 4 5 ?", repoId, indexName, true);
|
||||
|
||||
Response executeRepsonse = client().performRequest(new Request("PUT", "/_slm/policy/" + policyName + "/_execute"));
|
||||
|
||||
try (XContentParser parser = JsonXContent.jsonXContent.createParser(NamedXContentRegistry.EMPTY,
|
||||
DeprecationHandler.THROW_UNSUPPORTED_OPERATION, EntityUtils.toByteArray(executeRepsonse.getEntity()))) {
|
||||
final String snapshotName = parser.mapStrings().get("snapshot_name");
|
||||
|
||||
// Check that the executed snapshot shows up in the SLM output
|
||||
assertBusy(() -> {
|
||||
try {
|
||||
Response response = client().performRequest(new Request("GET", "/_slm/policy" + (randomBoolean() ? "" : "?human")));
|
||||
Map<String, Object> policyResponseMap;
|
||||
try (InputStream content = response.getEntity().getContent()) {
|
||||
policyResponseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), content, true);
|
||||
}
|
||||
assertThat(policyResponseMap.size(), greaterThan(0));
|
||||
Optional<Map<String, Object>> inProgress = Optional.ofNullable((Map<String, Object>) policyResponseMap.get(policyName))
|
||||
.map(policy -> (Map<String, Object>) policy.get("in_progress"));
|
||||
|
||||
if (inProgress.isPresent()) {
|
||||
Map<String, Object> inProgressMap = inProgress.get();
|
||||
assertThat(inProgressMap.get("name"), equalTo(snapshotName));
|
||||
assertNotNull(inProgressMap.get("uuid"));
|
||||
assertThat(inProgressMap.get("state"), equalTo("STARTED"));
|
||||
assertThat((long) inProgressMap.get("start_time_millis"), greaterThan(0L));
|
||||
assertNull(inProgressMap.get("failure"));
|
||||
} else {
|
||||
fail("expected in_progress to contain a running snapshot, but the response was " + policyResponseMap);
|
||||
}
|
||||
} catch (ResponseException e) {
|
||||
fail("expected policy to exist but it does not: " + EntityUtils.toString(e.getResponse().getEntity()));
|
||||
}
|
||||
});
|
||||
|
||||
// Cancel the snapshot since it is not going to complete quickly
|
||||
assertOK(client().performRequest(new Request("DELETE", "/_snapshot/" + repoId + "/" + snapshotName)));
|
||||
}
|
||||
|
||||
Request delReq = new Request("DELETE", "/_slm/policy/" + policyName);
|
||||
assertOK(client().performRequest(delReq));
|
||||
|
||||
// It's possible there could have been a snapshot in progress when the
|
||||
// policy is deleted, so wait for it to be finished
|
||||
assertBusy(() -> {
|
||||
assertThat(wipeSnapshots().size(), equalTo(0));
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Map<String, Object> extractMetadata(Map<String, Object> snapshotResponseMap, String snapshotPrefix) {
|
||||
List<Map<String, Object>> snapshots = ((List<Map<String, Object>>) snapshotResponseMap.get("snapshots"));
|
||||
|
@ -298,6 +360,10 @@ public class SnapshotLifecycleIT extends ESRestTestCase {
|
|||
}
|
||||
|
||||
private void inializeRepo(String repoName) throws IOException {
|
||||
inializeRepo(repoName, 256);
|
||||
}
|
||||
|
||||
private void inializeRepo(String repoName, int maxBytesPerSecond) throws IOException {
|
||||
Request request = new Request("PUT", "/_snapshot/" + repoName);
|
||||
request.setJsonEntity(Strings
|
||||
.toString(JsonXContent.contentBuilder()
|
||||
|
@ -306,7 +372,7 @@ public class SnapshotLifecycleIT extends ESRestTestCase {
|
|||
.startObject("settings")
|
||||
.field("compress", randomBoolean())
|
||||
.field("location", System.getProperty("tests.path.repo"))
|
||||
.field("max_snapshot_bytes_per_sec", "256b")
|
||||
.field("max_snapshot_bytes_per_sec", maxBytesPerSecond + "b")
|
||||
.endObject()
|
||||
.endObject()));
|
||||
assertOK(client().performRequest(request));
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.action.ActionListener;
|
|||
import org.elasticsearch.action.support.ActionFilters;
|
||||
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.SnapshotsInProgress;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
|
@ -21,14 +22,17 @@ import org.elasticsearch.common.io.stream.StreamInput;
|
|||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
import org.elasticsearch.xpack.core.slm.SnapshotLifecycleMetadata;
|
||||
import org.elasticsearch.xpack.core.slm.SnapshotLifecyclePolicy;
|
||||
import org.elasticsearch.xpack.core.slm.SnapshotLifecyclePolicyItem;
|
||||
import org.elasticsearch.xpack.core.slm.action.GetSnapshotLifecycleAction;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -61,10 +65,27 @@ public class TransportGetSnapshotLifecycleAction extends
|
|||
if (snapMeta == null) {
|
||||
listener.onResponse(new GetSnapshotLifecycleAction.Response(Collections.emptyList()));
|
||||
} else {
|
||||
final Map<String, SnapshotLifecyclePolicyItem.SnapshotInProgress> inProgress;
|
||||
SnapshotsInProgress sip = state.custom(SnapshotsInProgress.TYPE);
|
||||
if (sip == null) {
|
||||
inProgress = Collections.emptyMap();
|
||||
} else {
|
||||
inProgress = new HashMap<>();
|
||||
for (SnapshotsInProgress.Entry entry : sip.entries()) {
|
||||
Map<String, Object> meta = entry.userMetadata();
|
||||
if (meta == null ||
|
||||
meta.get(SnapshotLifecyclePolicy.POLICY_ID_METADATA_FIELD) == null ||
|
||||
(meta.get(SnapshotLifecyclePolicy.POLICY_ID_METADATA_FIELD) instanceof String == false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String policyId = (String) meta.get(SnapshotLifecyclePolicy.POLICY_ID_METADATA_FIELD);
|
||||
inProgress.put(policyId, SnapshotLifecyclePolicyItem.SnapshotInProgress.fromEntry(entry));
|
||||
}
|
||||
}
|
||||
|
||||
final Set<String> ids = new HashSet<>(Arrays.asList(request.getLifecycleIds()));
|
||||
List<SnapshotLifecyclePolicyItem> lifecycles = snapMeta.getSnapshotConfigurations()
|
||||
.values()
|
||||
.stream()
|
||||
List<SnapshotLifecyclePolicyItem> lifecycles = snapMeta.getSnapshotConfigurations().values().stream()
|
||||
.filter(meta -> {
|
||||
if (ids.isEmpty()) {
|
||||
return true;
|
||||
|
@ -72,7 +93,7 @@ public class TransportGetSnapshotLifecycleAction extends
|
|||
return ids.contains(meta.getPolicy().getId());
|
||||
}
|
||||
})
|
||||
.map(SnapshotLifecyclePolicyItem::new)
|
||||
.map(policyMeta -> new SnapshotLifecyclePolicyItem(policyMeta, inProgress.get(policyMeta.getPolicy().getId())))
|
||||
.collect(Collectors.toList());
|
||||
listener.onResponse(new GetSnapshotLifecycleAction.Response(lifecycles));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue