forked from opensearch-project/OpenSearch
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Remote Store] Add rest endpoint for remote store restore (opensearch…
…-project#3576) * Add rest endpoint for remote store restore Signed-off-by: Sachin Kale <kalsac@amazon.com>
- Loading branch information
1 parent
1bddbd5
commit e051d48
Showing
13 changed files
with
441 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
rest-api-spec/src/main/resources/rest-api-spec/api/remote_store.restore.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"remote_store.restore":{ | ||
"documentation":{ | ||
"url": "https://opensearch.org/docs/latest/opensearch/rest-api/remote-store#restore", | ||
"description":"Restores from remote store." | ||
}, | ||
"stability":"experimental", | ||
"url":{ | ||
"paths":[ | ||
{ | ||
"path":"/_remotestore/_restore", | ||
"methods":[ | ||
"POST" | ||
] | ||
} | ||
] | ||
}, | ||
"params":{ | ||
"cluster_manager_timeout":{ | ||
"type":"time", | ||
"description":"Explicit operation timeout for connection to cluster-manager node" | ||
}, | ||
"wait_for_completion":{ | ||
"type":"boolean", | ||
"description":"Should this request wait until the operation has completed before returning", | ||
"default":false | ||
} | ||
}, | ||
"body":{ | ||
"description":"A comma separated list of index IDs", | ||
"required":true | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
...ava/org/opensearch/action/admin/cluster/remotestore/restore/RestoreRemoteStoreAction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.action.admin.cluster.remotestore.restore; | ||
|
||
import org.opensearch.action.ActionType; | ||
|
||
/** | ||
* Restore remote store action | ||
* | ||
* @opensearch.internal | ||
*/ | ||
public final class RestoreRemoteStoreAction extends ActionType<RestoreRemoteStoreResponse> { | ||
|
||
public static final RestoreRemoteStoreAction INSTANCE = new RestoreRemoteStoreAction(); | ||
public static final String NAME = "cluster:admin/remotestore/restore"; | ||
|
||
private RestoreRemoteStoreAction() { | ||
super(NAME, RestoreRemoteStoreResponse::new); | ||
} | ||
} |
126 changes: 126 additions & 0 deletions
126
...a/org/opensearch/action/admin/cluster/remotestore/restore/RestoreRemoteStoreResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.action.admin.cluster.remotestore.restore; | ||
|
||
import org.opensearch.action.ActionResponse; | ||
import org.opensearch.common.Nullable; | ||
import org.opensearch.common.ParseField; | ||
import org.opensearch.common.io.stream.StreamInput; | ||
import org.opensearch.common.io.stream.StreamOutput; | ||
import org.opensearch.common.xcontent.ConstructingObjectParser; | ||
import org.opensearch.common.xcontent.ToXContentObject; | ||
import org.opensearch.common.xcontent.XContentBuilder; | ||
import org.opensearch.common.xcontent.XContentParser; | ||
import org.opensearch.rest.RestStatus; | ||
import org.opensearch.snapshots.RestoreInfo; | ||
|
||
import java.io.IOException; | ||
import java.util.Objects; | ||
|
||
import static org.opensearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; | ||
|
||
/** | ||
* Contains information about remote store restores | ||
* | ||
* @opensearch.internal | ||
*/ | ||
public final class RestoreRemoteStoreResponse extends ActionResponse implements ToXContentObject { | ||
|
||
@Nullable | ||
private final RestoreInfo restoreInfo; | ||
|
||
public RestoreRemoteStoreResponse(@Nullable RestoreInfo restoreInfo) { | ||
this.restoreInfo = restoreInfo; | ||
} | ||
|
||
public RestoreRemoteStoreResponse(StreamInput in) throws IOException { | ||
super(in); | ||
restoreInfo = RestoreInfo.readOptionalRestoreInfo(in); | ||
} | ||
|
||
/** | ||
* Returns restore information if remote store restore was completed before this method returned, null otherwise | ||
* | ||
* @return restore information or null | ||
*/ | ||
public RestoreInfo getRestoreInfo() { | ||
return restoreInfo; | ||
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { | ||
out.writeOptionalWriteable(restoreInfo); | ||
} | ||
|
||
public RestStatus status() { | ||
if (restoreInfo == null) { | ||
return RestStatus.ACCEPTED; | ||
} | ||
return restoreInfo.status(); | ||
} | ||
|
||
@Override | ||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
builder.startObject(); | ||
if (restoreInfo != null) { | ||
builder.field("remote_store"); | ||
restoreInfo.toXContent(builder, params); | ||
} else { | ||
builder.field("accepted", true); | ||
} | ||
builder.endObject(); | ||
return builder; | ||
} | ||
|
||
public static final ConstructingObjectParser<RestoreRemoteStoreResponse, Void> PARSER = new ConstructingObjectParser<>( | ||
"restore_remote_store", | ||
true, | ||
v -> { | ||
RestoreInfo restoreInfo = (RestoreInfo) v[0]; | ||
Boolean accepted = (Boolean) v[1]; | ||
assert (accepted == null && restoreInfo != null) || (accepted != null && accepted && restoreInfo == null) : "accepted: [" | ||
+ accepted | ||
+ "], restoreInfo: [" | ||
+ restoreInfo | ||
+ "]"; | ||
return new RestoreRemoteStoreResponse(restoreInfo); | ||
} | ||
); | ||
|
||
static { | ||
PARSER.declareObject( | ||
optionalConstructorArg(), | ||
(parser, context) -> RestoreInfo.fromXContent(parser), | ||
new ParseField("remote_store") | ||
); | ||
PARSER.declareBoolean(optionalConstructorArg(), new ParseField("accepted")); | ||
} | ||
|
||
public static RestoreRemoteStoreResponse fromXContent(XContentParser parser) throws IOException { | ||
return PARSER.parse(parser, null); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
RestoreRemoteStoreResponse that = (RestoreRemoteStoreResponse) o; | ||
return Objects.equals(restoreInfo, that.restoreInfo); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(restoreInfo); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "RestoreRemoteStoreResponse{" + "restoreInfo=" + restoreInfo + '}'; | ||
} | ||
} |
103 changes: 103 additions & 0 deletions
103
...pensearch/action/admin/cluster/remotestore/restore/TransportRestoreRemoteStoreAction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.action.admin.cluster.remotestore.restore; | ||
|
||
import org.opensearch.action.ActionListener; | ||
import org.opensearch.action.admin.cluster.snapshots.restore.RestoreClusterStateListener; | ||
import org.opensearch.action.support.ActionFilters; | ||
import org.opensearch.action.support.clustermanager.TransportClusterManagerNodeAction; | ||
import org.opensearch.cluster.ClusterState; | ||
import org.opensearch.cluster.block.ClusterBlockException; | ||
import org.opensearch.cluster.block.ClusterBlockLevel; | ||
import org.opensearch.cluster.metadata.IndexNameExpressionResolver; | ||
import org.opensearch.cluster.service.ClusterService; | ||
import org.opensearch.common.inject.Inject; | ||
import org.opensearch.common.io.stream.StreamInput; | ||
import org.opensearch.snapshots.RestoreService; | ||
import org.opensearch.threadpool.ThreadPool; | ||
import org.opensearch.transport.TransportService; | ||
|
||
import java.io.IOException; | ||
|
||
/** | ||
* Transport action for restore remote store operation | ||
* | ||
* @opensearch.internal | ||
*/ | ||
public final class TransportRestoreRemoteStoreAction extends TransportClusterManagerNodeAction< | ||
RestoreRemoteStoreRequest, | ||
RestoreRemoteStoreResponse> { | ||
private final RestoreService restoreService; | ||
|
||
@Inject | ||
public TransportRestoreRemoteStoreAction( | ||
TransportService transportService, | ||
ClusterService clusterService, | ||
ThreadPool threadPool, | ||
RestoreService restoreService, | ||
ActionFilters actionFilters, | ||
IndexNameExpressionResolver indexNameExpressionResolver | ||
) { | ||
super( | ||
RestoreRemoteStoreAction.NAME, | ||
transportService, | ||
clusterService, | ||
threadPool, | ||
actionFilters, | ||
RestoreRemoteStoreRequest::new, | ||
indexNameExpressionResolver | ||
); | ||
this.restoreService = restoreService; | ||
} | ||
|
||
@Override | ||
protected String executor() { | ||
return ThreadPool.Names.GENERIC; | ||
} | ||
|
||
@Override | ||
protected RestoreRemoteStoreResponse read(StreamInput in) throws IOException { | ||
return new RestoreRemoteStoreResponse(in); | ||
} | ||
|
||
@Override | ||
protected ClusterBlockException checkBlock(RestoreRemoteStoreRequest request, ClusterState state) { | ||
// Restoring a remote store might change the global state and create/change an index, | ||
// so we need to check for METADATA_WRITE and WRITE blocks | ||
ClusterBlockException blockException = state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); | ||
if (blockException != null) { | ||
return blockException; | ||
} | ||
return state.blocks().globalBlockedException(ClusterBlockLevel.WRITE); | ||
|
||
} | ||
|
||
@Override | ||
protected void clusterManagerOperation( | ||
final RestoreRemoteStoreRequest request, | ||
final ClusterState state, | ||
final ActionListener<RestoreRemoteStoreResponse> listener | ||
) { | ||
restoreService.restoreFromRemoteStore( | ||
request, | ||
ActionListener.delegateFailure(listener, (delegatedListener, restoreCompletionResponse) -> { | ||
if (restoreCompletionResponse.getRestoreInfo() == null && request.waitForCompletion()) { | ||
RestoreClusterStateListener.createAndRegisterListener( | ||
clusterService, | ||
restoreCompletionResponse, | ||
delegatedListener, | ||
RestoreRemoteStoreResponse::new | ||
); | ||
} else { | ||
delegatedListener.onResponse(new RestoreRemoteStoreResponse(restoreCompletionResponse.getRestoreInfo())); | ||
} | ||
}) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.