diff --git a/server/src/main/java/org/opensearch/cluster/decommission/DecommissionService.java b/server/src/main/java/org/opensearch/cluster/decommission/DecommissionService.java index f82b432345545..6e63ea0bf4766 100644 --- a/server/src/main/java/org/opensearch/cluster/decommission/DecommissionService.java +++ b/server/src/main/java/org/opensearch/cluster/decommission/DecommissionService.java @@ -16,6 +16,7 @@ import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.ClusterStateUpdateTask; import org.opensearch.cluster.NotClusterManagerException; +import org.opensearch.cluster.ack.ClusterStateUpdateResponse; import org.opensearch.cluster.coordination.CoordinationMetadata; import org.opensearch.cluster.metadata.DecommissionAttributeMetadata; import org.opensearch.cluster.coordination.ClusterBootstrapService; @@ -415,6 +416,40 @@ private static void ensureNoAwarenessAttributeDecommissioned( } } + public void clearDecommissionStatus(final ActionListener listener) { + // Execute cluster update to remove decommission attribute from cluster state metadata. + clusterService.submitStateUpdateTask( + "delete_decommission", + new ClusterStateUpdateTask(Priority.URGENT) { + @Override + public ClusterState execute(ClusterState currentState) { + return deleteDecommissionAttribute(currentState); + } + + @Override + public void onFailure(String source, Exception e) { + logger.error(() -> new ParameterizedMessage("Failed to clear decommission attribute."), e); + listener.onFailure(e); + } + + @Override + public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) { + // Once the cluster state is processed we can try to recommission nodes by setting the weights for the zone. + // TODO Set the weights for the recommissioning zone. + listener.onResponse(new ClusterStateUpdateResponse(true)); + } + } + ); + } + + ClusterState deleteDecommissionAttribute(final ClusterState currentState) { + logger.info("Delete decommission request received"); + Metadata metadata = currentState.metadata(); + Metadata.Builder mdBuilder = Metadata.builder(metadata); + mdBuilder.removeCustom(DecommissionAttributeMetadata.TYPE); + return ClusterState.builder(currentState).metadata(mdBuilder).build(); + } + private static void ensureNoQuorumLossDueToDecommissioning( DecommissionAttribute decommissionAttribute, Set clusterManagerNodesToBeDecommissioned, diff --git a/server/src/test/java/org/opensearch/cluster/decommission/DecommissionServiceTests.java b/server/src/test/java/org/opensearch/cluster/decommission/DecommissionServiceTests.java index eb78f4e58114f..1ad0c5b5e2716 100644 --- a/server/src/test/java/org/opensearch/cluster/decommission/DecommissionServiceTests.java +++ b/server/src/test/java/org/opensearch/cluster/decommission/DecommissionServiceTests.java @@ -199,6 +199,23 @@ public void testDecommissioningNotInitiatedWhenNotEnoughClusterManagerNodes() { assertThat(e.getMessage(), Matchers.endsWith("cannot proceed with decommission request. Cluster might go into quorum loss")); } + public void testClearDecommissionAttribute() { + final ClusterSettings settings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); + DecommissionAttribute decommissionAttribute = new DecommissionAttribute("zone", "zone-2"); + org.opensearch.cluster.metadata.DecommissionAttributeMetadata decommissionAttributeMetadata = + new org.opensearch.cluster.metadata.DecommissionAttributeMetadata(decommissionAttribute, DecommissionStatus.DECOMMISSION_SUCCESSFUL); + ClusterState clusterState = ClusterState.builder(new ClusterName("test")) + .metadata(Metadata.builder() + .putCustom(org.opensearch.cluster.metadata.DecommissionAttributeMetadata.TYPE, decommissionAttributeMetadata).build()) + .build(); + + final ClusterState newClusterState = this.decommissionService.deleteDecommissionAttribute(clusterState); + org.opensearch.cluster.metadata.DecommissionAttributeMetadata metadata = newClusterState.metadata().custom(org.opensearch.cluster.metadata.DecommissionAttributeMetadata.TYPE); + + // Decommission Attribute should be removed. + assertNull(metadata); + } + private ClusterState addDataNodes(ClusterState clusterState, String zone, String... nodeIds) { DiscoveryNodes.Builder nodeBuilder = DiscoveryNodes.builder(clusterState.nodes()); org.opensearch.common.collect.List.of(nodeIds).forEach(nodeId -> nodeBuilder.add(newDataNode(nodeId, singletonMap("zone", zone))));