use of org.opensearch.action.admin.indices.close.CloseIndexResponse.IndexResult in project OpenSearch by opensearch-project.
the class MetadataIndexStateService method closeIndices.
/**
* Closes one or more indices.
*
* Closing indices is a 3 steps process: it first adds a write block to every indices to close, then waits for the operations on shards
* to be terminated and finally closes the indices by moving their state to CLOSE.
*/
public void closeIndices(final CloseIndexClusterStateUpdateRequest request, final ActionListener<CloseIndexResponse> listener) {
final Index[] concreteIndices = request.indices();
if (concreteIndices == null || concreteIndices.length == 0) {
throw new IllegalArgumentException("Index name is required");
}
List<String> writeIndices = new ArrayList<>();
SortedMap<String, IndexAbstraction> lookup = clusterService.state().metadata().getIndicesLookup();
for (Index index : concreteIndices) {
IndexAbstraction ia = lookup.get(index.getName());
if (ia != null && ia.getParentDataStream() != null && ia.getParentDataStream().getWriteIndex().getIndex().equals(index)) {
writeIndices.add(index.getName());
}
}
if (writeIndices.size() > 0) {
throw new IllegalArgumentException("cannot close the following data stream write indices [" + Strings.collectionToCommaDelimitedString(writeIndices) + "]");
}
clusterService.submitStateUpdateTask("add-block-index-to-close " + Arrays.toString(concreteIndices), new ClusterStateUpdateTask(Priority.URGENT) {
private final Map<Index, ClusterBlock> blockedIndices = new HashMap<>();
@Override
public ClusterState execute(final ClusterState currentState) {
return addIndexClosedBlocks(concreteIndices, blockedIndices, currentState);
}
@Override
public void clusterStateProcessed(final String source, final ClusterState oldState, final ClusterState newState) {
if (oldState == newState) {
assert blockedIndices.isEmpty() : "List of blocked indices is not empty but cluster state wasn't changed";
listener.onResponse(new CloseIndexResponse(true, false, Collections.emptyList()));
} else {
assert blockedIndices.isEmpty() == false : "List of blocked indices is empty but cluster state was changed";
threadPool.executor(ThreadPool.Names.MANAGEMENT).execute(new WaitForClosedBlocksApplied(blockedIndices, request, ActionListener.wrap(verifyResults -> clusterService.submitStateUpdateTask("close-indices", new ClusterStateUpdateTask(Priority.URGENT) {
private final List<IndexResult> indices = new ArrayList<>();
@Override
public ClusterState execute(final ClusterState currentState) throws Exception {
Tuple<ClusterState, Collection<IndexResult>> closingResult = closeRoutingTable(currentState, blockedIndices, verifyResults);
assert verifyResults.size() == closingResult.v2().size();
indices.addAll(closingResult.v2());
return allocationService.reroute(closingResult.v1(), "indices closed");
}
@Override
public void onFailure(final String source, final Exception e) {
listener.onFailure(e);
}
@Override
public void clusterStateProcessed(final String source, final ClusterState oldState, final ClusterState newState) {
final boolean acknowledged = indices.stream().noneMatch(IndexResult::hasFailures);
final String[] waitForIndices = indices.stream().filter(result -> result.hasFailures() == false).filter(result -> newState.routingTable().hasIndex(result.getIndex())).map(result -> result.getIndex().getName()).toArray(String[]::new);
if (waitForIndices.length > 0) {
activeShardsObserver.waitForActiveShards(waitForIndices, request.waitForActiveShards(), request.ackTimeout(), shardsAcknowledged -> {
if (shardsAcknowledged == false) {
logger.debug("[{}] indices closed, but the operation timed out while waiting " + "for enough shards to be started.", Arrays.toString(waitForIndices));
}
// acknowledged maybe be false but some indices may have been correctly
// closed, so
// we maintain a kind of coherency by overriding the shardsAcknowledged
// value
// (see ShardsAcknowledgedResponse constructor)
boolean shardsAcked = acknowledged ? shardsAcknowledged : false;
listener.onResponse(new CloseIndexResponse(acknowledged, shardsAcked, indices));
}, listener::onFailure);
} else {
listener.onResponse(new CloseIndexResponse(acknowledged, false, indices));
}
}
}), listener::onFailure)));
}
}
@Override
public void onFailure(final String source, final Exception e) {
listener.onFailure(e);
}
@Override
public TimeValue timeout() {
return request.masterNodeTimeout();
}
});
}
use of org.opensearch.action.admin.indices.close.CloseIndexResponse.IndexResult in project OpenSearch by opensearch-project.
the class MetadataIndexStateService method closeRoutingTable.
/**
* Step 3 - Move index states from OPEN to CLOSE in cluster state for indices that are ready for closing.
*/
static Tuple<ClusterState, Collection<IndexResult>> closeRoutingTable(final ClusterState currentState, final Map<Index, ClusterBlock> blockedIndices, final Map<Index, IndexResult> verifyResult) {
// Remove the index routing table of closed indices if the cluster is in a mixed version
// that does not support the replication of closed indices
final boolean removeRoutingTable = currentState.nodes().getMinNodeVersion().before(LegacyESVersion.V_7_2_0);
final Metadata.Builder metadata = Metadata.builder(currentState.metadata());
final ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks());
final RoutingTable.Builder routingTable = RoutingTable.builder(currentState.routingTable());
final Set<String> closedIndices = new HashSet<>();
Map<Index, IndexResult> closingResults = new HashMap<>(verifyResult);
for (Map.Entry<Index, IndexResult> result : verifyResult.entrySet()) {
final Index index = result.getKey();
final boolean acknowledged = result.getValue().hasFailures() == false;
try {
if (acknowledged == false) {
logger.debug("verification of shards before closing {} failed [{}]", index, result);
continue;
}
final IndexMetadata indexMetadata = metadata.getSafe(index);
if (indexMetadata.getState() == IndexMetadata.State.CLOSE) {
logger.debug("verification of shards before closing {} succeeded but index is already closed", index);
assert currentState.blocks().hasIndexBlock(index.getName(), INDEX_CLOSED_BLOCK);
continue;
}
final ClusterBlock closingBlock = blockedIndices.get(index);
assert closingBlock != null;
if (currentState.blocks().hasIndexBlock(index.getName(), closingBlock) == false) {
// we should report error in this case as the index can be left as open.
closingResults.put(result.getKey(), new IndexResult(result.getKey(), new IllegalStateException("verification of shards before closing " + index + " succeeded but block has been removed in the meantime")));
logger.debug("verification of shards before closing {} succeeded but block has been removed in the meantime", index);
continue;
}
// Check if index closing conflicts with any running restores
Set<Index> restoringIndices = RestoreService.restoringIndices(currentState, singleton(index));
if (restoringIndices.isEmpty() == false) {
closingResults.put(result.getKey(), new IndexResult(result.getKey(), new IllegalStateException("verification of shards before closing " + index + " succeeded but index is being restored in the meantime")));
logger.debug("verification of shards before closing {} succeeded but index is being restored in the meantime", index);
continue;
}
// Check if index closing conflicts with any running snapshots
Set<Index> snapshottingIndices = SnapshotsService.snapshottingIndices(currentState, singleton(index));
if (snapshottingIndices.isEmpty() == false) {
closingResults.put(result.getKey(), new IndexResult(result.getKey(), new IllegalStateException("verification of shards before closing " + index + " succeeded but index is being snapshot in the meantime")));
logger.debug("verification of shards before closing {} succeeded but index is being snapshot in the meantime", index);
continue;
}
blocks.removeIndexBlockWithId(index.getName(), INDEX_CLOSED_BLOCK_ID);
blocks.addIndexBlock(index.getName(), INDEX_CLOSED_BLOCK);
final IndexMetadata.Builder updatedMetadata = IndexMetadata.builder(indexMetadata).state(IndexMetadata.State.CLOSE);
if (removeRoutingTable) {
metadata.put(updatedMetadata);
routingTable.remove(index.getName());
} else {
metadata.put(updatedMetadata.settingsVersion(indexMetadata.getSettingsVersion() + 1).settings(Settings.builder().put(indexMetadata.getSettings()).put(VERIFIED_BEFORE_CLOSE_SETTING.getKey(), true)));
routingTable.addAsFromOpenToClose(metadata.getSafe(index));
}
logger.debug("closing index {} succeeded", index);
closedIndices.add(index.getName());
} catch (final IndexNotFoundException e) {
logger.debug("index {} has been deleted since it was blocked before closing, ignoring", index);
}
}
logger.info("completed closing of indices {}", closedIndices);
return Tuple.tuple(ClusterState.builder(currentState).blocks(blocks).metadata(metadata).routingTable(routingTable.build()).build(), closingResults.values());
}
use of org.opensearch.action.admin.indices.close.CloseIndexResponse.IndexResult in project OpenSearch by opensearch-project.
the class CloseIndexResponseTests method testToXContent.
/**
* Test that random responses can be written to xcontent without errors.
* Also check some specific simple cases for output.
*/
public void testToXContent() throws IOException {
CloseIndexResponse response = randomResponse();
XContentType xContentType = randomFrom(XContentType.values());
try (XContentBuilder builder = XContentBuilder.builder(xContentType.xContent())) {
response.toXContent(builder, ToXContent.EMPTY_PARAMS);
}
Index index = new Index("test", "uuid");
IndexResult indexResult = new CloseIndexResponse.IndexResult(index);
CloseIndexResponse closeIndexResponse = new CloseIndexResponse(true, true, Collections.singletonList(indexResult));
assertEquals("{\"acknowledged\":true,\"shards_acknowledged\":true,\"indices\":{\"test\":{\"closed\":true}}}", Strings.toString(closeIndexResponse));
CloseIndexResponse.ShardResult[] shards = new CloseIndexResponse.ShardResult[1];
shards[0] = new CloseIndexResponse.ShardResult(0, new CloseIndexResponse.ShardResult.Failure[] { new CloseIndexResponse.ShardResult.Failure("test", 0, new ActionNotFoundTransportException("test"), "nodeId") });
indexResult = new CloseIndexResponse.IndexResult(index, shards);
closeIndexResponse = new CloseIndexResponse(true, true, Collections.singletonList(indexResult));
assertEquals("{\"acknowledged\":true,\"shards_acknowledged\":true," + "\"indices\":{\"test\":{\"closed\":false,\"failedShards\":{\"0\":{" + "\"failures\":[{\"node\":\"nodeId\",\"shard\":0,\"index\":\"test\",\"status\":\"INTERNAL_SERVER_ERROR\"," + "\"reason\":{\"type\":\"action_not_found_transport_exception\"," + "\"reason\":\"No handler for action [test]\"}}]}}}}}", Strings.toString(closeIndexResponse));
}
use of org.opensearch.action.admin.indices.close.CloseIndexResponse.IndexResult in project OpenSearch by opensearch-project.
the class MetadataIndexStateServiceTests method testCloseRoutingTableWithRestoredIndex.
public void testCloseRoutingTableWithRestoredIndex() {
ClusterState state = ClusterState.builder(new ClusterName("testCloseRoutingTableWithRestoredIndex")).build();
String indexName = "restored-index";
ClusterBlock block = MetadataIndexStateService.createIndexClosingBlock();
state = addRestoredIndex(indexName, randomIntBetween(1, 5), randomIntBetween(0, 5), state);
state = ClusterState.builder(state).blocks(ClusterBlocks.builder().blocks(state.blocks()).addIndexBlock(indexName, block)).build();
final Index index = state.metadata().index(indexName).getIndex();
final ClusterState updatedState = MetadataIndexStateService.closeRoutingTable(state, singletonMap(index, block), singletonMap(index, new IndexResult(index))).v1();
assertIsOpened(index.getName(), updatedState);
assertThat(updatedState.blocks().hasIndexBlockWithId(index.getName(), INDEX_CLOSED_BLOCK_ID), is(true));
}
use of org.opensearch.action.admin.indices.close.CloseIndexResponse.IndexResult in project OpenSearch by opensearch-project.
the class MetadataIndexStateServiceTests method testCloseFailedIfBlockDisappeared.
public void testCloseFailedIfBlockDisappeared() {
ClusterState state = ClusterState.builder(new ClusterName("failedIfBlockDisappeared")).build();
Map<Index, ClusterBlock> blockedIndices = new HashMap<>();
int numIndices = between(1, 10);
Set<Index> disappearedIndices = new HashSet<>();
Map<Index, IndexResult> verifyResults = new HashMap<>();
for (int i = 0; i < numIndices; i++) {
String indexName = "test-" + i;
state = addOpenedIndex(indexName, randomIntBetween(1, 3), randomIntBetween(0, 3), state);
Index index = state.metadata().index(indexName).getIndex();
state = MetadataIndexStateService.addIndexClosedBlocks(new Index[] { index }, blockedIndices, state);
if (randomBoolean()) {
state = ClusterState.builder(state).blocks(ClusterBlocks.builder().blocks(state.blocks()).removeIndexBlocks(indexName).build()).build();
disappearedIndices.add(index);
}
verifyResults.put(index, new IndexResult(index));
}
Collection<IndexResult> closingResults = MetadataIndexStateService.closeRoutingTable(state, blockedIndices, unmodifiableMap(verifyResults)).v2();
assertThat(closingResults, hasSize(numIndices));
Set<Index> failedIndices = closingResults.stream().filter(IndexResult::hasFailures).map(IndexResult::getIndex).collect(Collectors.toSet());
assertThat(failedIndices, equalTo(disappearedIndices));
}
Aggregations