Skip to content

Commit

Permalink
Add ability to get snapshot status for running snapshots
Browse files Browse the repository at this point in the history
Closes #4946
  • Loading branch information
imotov committed Mar 18, 2014
1 parent fe48737 commit a119204
Show file tree
Hide file tree
Showing 30 changed files with 2,423 additions and 34 deletions.
36 changes: 35 additions & 1 deletion docs/reference/modules/snapshots.asciidoc
Expand Up @@ -175,7 +175,7 @@ started by mistake.
[float]
=== Restore

A snapshot can be restored using this following command:
A snapshot can be restored using the following command:

[source,shell]
-----------------------------------
Expand Down Expand Up @@ -205,3 +205,37 @@ closed. The restore operation automatically opens restored indices if they were
didn't exist in the cluster. If cluster state is restored, the restored templates that don't currently exist in the
cluster are added and existing templates with the same name are replaced by the restored templates. The restored
persistent settings are added to the existing persistent settings.


[float]
=== Snapshot status

A list of currently running snapshots with their detailed status information can be obtained using the following command:

[source,shell]
-----------------------------------
$ curl -XGET "localhost:9200/_snapshot/_status"
-----------------------------------

In this format, the command will return information about all currently running snapshots. By specifying a repository name, it's possible
to limit the results to a particular repository:

[source,shell]
-----------------------------------
$ curl -XGET "localhost:9200/_snapshot/my_backup/_status"
-----------------------------------

If both repository name and snapshot id are specified, this command will return detailed status information for the given snapshot even
if it's not currently running:

[source,shell]
-----------------------------------
$ curl -XGET "localhost:9200/_snapshot/my_backup/snapshot_1/_status"
-----------------------------------

Multiple ids are also supported:

[source,shell]
-----------------------------------
$ curl -XGET "localhost:9200/_snapshot/my_backup/snapshot_1,snapshot_2/_status"
-----------------------------------
27 changes: 27 additions & 0 deletions rest-api-spec/api/snapshot.status.json
@@ -0,0 +1,27 @@
{
"snapshot.status": {
"documentation": "http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/modules-snapshots.html",
"methods": ["GET"],
"url": {
"path": "/_snapshot/_status",
"paths": ["/_snapshot/_status", "/_snapshot/{repository}/_status", "/_snapshot/{repository}/{snapshot}/_status"],
"parts": {
"repository": {
"type": "string",
"description": "A repository name"
},
"snapshot": {
"type": "list",
"description": "A comma-separated list of snapshot names"
}
},
"params": {
"master_timeout": {
"type" : "time",
"description" : "Explicit operation timeout for connection to master node"
}
}
},
"body": null
}
}
3 changes: 3 additions & 0 deletions src/main/java/org/elasticsearch/action/ActionModule.java
Expand Up @@ -52,6 +52,8 @@
import org.elasticsearch.action.admin.cluster.snapshots.get.TransportGetSnapshotsAction;
import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotAction;
import org.elasticsearch.action.admin.cluster.snapshots.restore.TransportRestoreSnapshotAction;
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusAction;
import org.elasticsearch.action.admin.cluster.snapshots.status.TransportSnapshotsStatusAction;
import org.elasticsearch.action.admin.cluster.state.ClusterStateAction;
import org.elasticsearch.action.admin.cluster.state.TransportClusterStateAction;
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsAction;
Expand Down Expand Up @@ -214,6 +216,7 @@ protected void configure() {
registerAction(DeleteSnapshotAction.INSTANCE, TransportDeleteSnapshotAction.class);
registerAction(CreateSnapshotAction.INSTANCE, TransportCreateSnapshotAction.class);
registerAction(RestoreSnapshotAction.INSTANCE, TransportRestoreSnapshotAction.class);
registerAction(SnapshotsStatusAction.INSTANCE, TransportSnapshotsStatusAction.class);

registerAction(IndicesStatsAction.INSTANCE, TransportIndicesStatsAction.class);
registerAction(IndicesStatusAction.INSTANCE, TransportIndicesStatusAction.class);
Expand Down
@@ -0,0 +1,98 @@
/*
* 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
*
* 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.action.admin.cluster.snapshots.status;

import org.elasticsearch.ElasticsearchIllegalArgumentException;

/**
*/
public enum SnapshotIndexShardStage {

/**
* Snapshot hasn't started yet
*/
INIT((byte)0, false),
/**
* Index files are being copied
*/
STARTED((byte)1, false),
/**
* Snapshot metadata is being written
*/
FINALIZE((byte)2, false),
/**
* Snapshot completed successfully
*/
DONE((byte)3, true),
/**
* Snapshot failed
*/
FAILURE((byte)4, true);

private byte value;

private boolean completed;

private SnapshotIndexShardStage(byte value, boolean completed) {
this.value = value;
this.completed = completed;
}

/**
* Returns code that represents the snapshot state
*
* @return code for the state
*/
public byte value() {
return value;
}

/**
* Returns true if snapshot completed (successfully or not)
*
* @return true if snapshot completed, false otherwise
*/
public boolean completed() {
return completed;
}

/**
* Generate snapshot state from code
*
* @param value the state code
* @return state
*/
public static SnapshotIndexShardStage fromValue(byte value) {
switch (value) {
case 0:
return INIT;
case 1:
return STARTED;
case 2:
return FINALIZE;
case 3:
return DONE;
case 4:
return FAILURE;
default:
throw new ElasticsearchIllegalArgumentException("No snapshot shard stage for value [" + value + "]");
}
}
}
@@ -0,0 +1,157 @@
/*
* 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
*
* 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.action.admin.cluster.snapshots.status;

import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationResponse;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentBuilderString;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.index.snapshots.IndexShardSnapshotStatus;

import java.io.IOException;

/**
*/
public class SnapshotIndexShardStatus extends BroadcastShardOperationResponse implements ToXContent {

private SnapshotIndexShardStage stage = SnapshotIndexShardStage.INIT;

private SnapshotStats stats;

private String nodeId;

private String failure;

private SnapshotIndexShardStatus() {
}

SnapshotIndexShardStatus(String index, int shardId, SnapshotIndexShardStage stage) {
super(index, shardId);
this.stage = stage;
}

SnapshotIndexShardStatus(ShardId shardId, IndexShardSnapshotStatus indexShardStatus) {
this(shardId, indexShardStatus, null);
}

SnapshotIndexShardStatus(ShardId shardId, IndexShardSnapshotStatus indexShardStatus, String nodeId) {
super(shardId.getIndex(), shardId.getId());
switch (indexShardStatus.stage()) {
case INIT:
stage = SnapshotIndexShardStage.INIT;
break;
case STARTED:
stage = SnapshotIndexShardStage.STARTED;
break;
case FINALIZE:
stage = SnapshotIndexShardStage.FINALIZE;
break;
case DONE:
stage = SnapshotIndexShardStage.DONE;
break;
case FAILURE:
stage = SnapshotIndexShardStage.FAILURE;
break;
default:
throw new ElasticsearchIllegalArgumentException("Unknown stage type " + indexShardStatus.stage());
}
stats = new SnapshotStats(indexShardStatus);
failure = indexShardStatus.failure();
this.nodeId = nodeId;
}

/**
* Returns snapshot stage
*/
public SnapshotIndexShardStage getStage() {
return stage;
}

/**
* Returns snapshot stats
*/
public SnapshotStats getStats() {
return stats;
}

/**
* Returns node id of the node where snapshot is currently running
*/
public String getNodeId() {
return nodeId;
}

/**
* Returns reason for snapshot failure
*/
public String getFailure() {
return failure;
}


public static SnapshotIndexShardStatus readShardSnapshotStatus(StreamInput in) throws IOException {
SnapshotIndexShardStatus shardStatus = new SnapshotIndexShardStatus();
shardStatus.readFrom(in);
return shardStatus;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeByte(stage.value());
stats.writeTo(out);
out.writeOptionalString(nodeId);
out.writeOptionalString(failure);
}

@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
stage = SnapshotIndexShardStage.fromValue(in.readByte());
stats = SnapshotStats.readSnapshotStats(in);
nodeId = in.readOptionalString();
failure = in.readOptionalString();
}

static final class Fields {
static final XContentBuilderString STAGE = new XContentBuilderString("stage");
static final XContentBuilderString REASON = new XContentBuilderString("reason");
static final XContentBuilderString NODE = new XContentBuilderString("node");
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(Integer.toString(getShardId()));
builder.field(Fields.STAGE, getStage());
stats.toXContent(builder, params);
if (getNodeId() != null) {
builder.field(Fields.NODE, getNodeId());
}
if (getFailure() != null) {
builder.field(Fields.REASON, getFailure());
}
builder.endObject();
return builder;
}
}

0 comments on commit a119204

Please sign in to comment.