This is an automated email from the ASF dual-hosted git repository.
xyuanlu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/helix.git
The following commit(s) were added to refs/heads/master by this push:
new 054d77ad5 Instance Evacuation prevent baseline re-computation after
dropped (#2740)
054d77ad5 is described below
commit 054d77ad577d7a0823cf9dfb360b544191d51e57
Author: Zachary Pinto <[email protected]>
AuthorDate: Mon Jan 29 16:18:30 2024 -0800
Instance Evacuation prevent baseline re-computation after dropped (#2740)
Instance Evacuation logic is moved to BaseControllerDataProvider cache and
will only cause baseline recalculation when the evacuate is triggered instead
of evacuating the node and then recalculating baseline after node is dropped
causing more shuffling. Also fix getAllLiveInstances to exclude
TimedOutForMaintenance nodes.
---
.../dataproviders/BaseControllerDataProvider.java | 31 ++++++++++++-----
.../controller/rebalancer/AbstractRebalancer.java | 2 +-
.../rebalancer/DelayedAutoRebalancer.java | 18 +++-------
.../rebalancer/util/DelayedRebalanceUtil.java | 20 +++--------
.../rebalancer/waged/WagedRebalancer.java | 10 ++----
.../org/apache/helix/manager/zk/ZKHelixAdmin.java | 4 ++-
.../rebalancer/TestInstanceOperation.java | 14 ++++++--
.../helix/rest/server/TestPerInstanceAccessor.java | 39 +++++++++++-----------
8 files changed, 70 insertions(+), 68 deletions(-)
diff --git
a/helix-core/src/main/java/org/apache/helix/controller/dataproviders/BaseControllerDataProvider.java
b/helix-core/src/main/java/org/apache/helix/controller/dataproviders/BaseControllerDataProvider.java
index 761fb6974..c6c799dd1 100644
---
a/helix-core/src/main/java/org/apache/helix/controller/dataproviders/BaseControllerDataProvider.java
+++
b/helix-core/src/main/java/org/apache/helix/controller/dataproviders/BaseControllerDataProvider.java
@@ -128,7 +128,9 @@ public class BaseControllerDataProvider implements
ControlContextProvider {
private final Set<String> _enabledSwapInInstanceNames = new HashSet<>();
private final Map<String, MonitoredAbnormalResolver>
_abnormalStateResolverMap = new HashMap<>();
private final Set<String> _timedOutInstanceDuringMaintenance = new
HashSet<>();
- private Map<String, LiveInstance> _liveInstanceExcludeTimedOutForMaintenance
= new HashMap<>();
+ private Map<String, LiveInstance>
_allLiveInstanceExcludeTimedOutForMaintenance = new HashMap<>();
+ private Map<String, LiveInstance>
_assignableLiveInstanceExcludeTimedOutForMaintenance =
+ new HashMap<>();
public BaseControllerDataProvider() {
this(AbstractDataCache.UNKNOWN_CLUSTER,
AbstractDataCache.UNKNOWN_PIPELINE);
@@ -345,7 +347,6 @@ public class BaseControllerDataProvider implements
ControlContextProvider {
* Refreshes the assignable instances and SWAP related caches. This should
be called after
* liveInstance and instanceConfig caches are refreshed. To determine what
instances are
* assignable and live, it takes a combination of both the all
instanceConfigs and liveInstances.
- * TODO: Add EVACUATE InstanceOperation to be filtered out in assignable
nodes.
*
* @param instanceConfigMap InstanceConfig map from instanceConfig cache
* @param liveInstancesMap LiveInstance map from liveInstance cache
@@ -406,7 +407,9 @@ public class BaseControllerDataProvider implements
ControlContextProvider {
_assignableInstanceConfigMap.put(node, currentInstanceConfig);
filteredInstancesByLogicalId.put(currentInstanceLogicalId, node);
}
- } else {
+ } else if (!currentInstanceConfig.getInstanceOperation()
+ .equals(InstanceConstants.InstanceOperation.EVACUATE.name())) {
+ // EVACUATE instances are not considered to be assignable.
_assignableInstanceConfigMap.put(node, currentInstanceConfig);
filteredInstancesByLogicalId.put(currentInstanceLogicalId, node);
}
@@ -472,7 +475,8 @@ public class BaseControllerDataProvider implements
ControlContextProvider {
// If maintenance mode has exited, clear cached timed-out nodes
if (!_isMaintenanceModeEnabled) {
_timedOutInstanceDuringMaintenance.clear();
- _liveInstanceExcludeTimedOutForMaintenance.clear();
+ _allLiveInstanceExcludeTimedOutForMaintenance.clear();
+ _assignableLiveInstanceExcludeTimedOutForMaintenance.clear();
}
}
@@ -484,21 +488,26 @@ public class BaseControllerDataProvider implements
ControlContextProvider {
timeOutWindow = clusterConfig.getOfflineNodeTimeOutForMaintenanceMode();
}
if (timeOutWindow >= 0 && isMaintenanceModeEnabled) {
- for (String instance : _assignableLiveInstancesMap.keySet()) {
+ for (String instance : _allLiveInstanceCache.getPropertyMap().keySet()) {
// 1. Check timed-out cache and don't do repeated work;
// 2. Check for nodes that didn't exist in the last iteration, because
it has been checked;
// 3. For all other nodes, check if it's timed-out.
// When maintenance mode is first entered, all nodes will be checked
as a result.
if (!_timedOutInstanceDuringMaintenance.contains(instance)
- &&
!_liveInstanceExcludeTimedOutForMaintenance.containsKey(instance)
+ &&
!_allLiveInstanceExcludeTimedOutForMaintenance.containsKey(instance)
&& isInstanceTimedOutDuringMaintenance(accessor, instance,
timeOutWindow)) {
_timedOutInstanceDuringMaintenance.add(instance);
}
}
}
if (isMaintenanceModeEnabled) {
- _liveInstanceExcludeTimedOutForMaintenance =
_assignableLiveInstancesMap.entrySet().stream()
- .filter(e ->
!_timedOutInstanceDuringMaintenance.contains(e.getKey()))
+ _allLiveInstanceExcludeTimedOutForMaintenance =
+ _allLiveInstanceCache.getPropertyMap().entrySet().stream()
+ .filter(e ->
!_timedOutInstanceDuringMaintenance.contains(e.getKey()))
+ .collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue));
+ _assignableLiveInstanceExcludeTimedOutForMaintenance =
+ _assignableLiveInstancesMap.entrySet().stream()
+ .filter(e ->
!_timedOutInstanceDuringMaintenance.contains(e.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue));
}
}
@@ -649,7 +658,7 @@ public class BaseControllerDataProvider implements
ControlContextProvider {
*/
public Map<String, LiveInstance> getAssignableLiveInstances() {
if (isMaintenanceModeEnabled()) {
- return
Collections.unmodifiableMap(_liveInstanceExcludeTimedOutForMaintenance);
+ return
Collections.unmodifiableMap(_assignableLiveInstanceExcludeTimedOutForMaintenance);
}
return Collections.unmodifiableMap(_assignableLiveInstancesMap);
@@ -663,6 +672,10 @@ public class BaseControllerDataProvider implements
ControlContextProvider {
* @return A map of LiveInstances to their instance names
*/
public Map<String, LiveInstance> getLiveInstances() {
+ if (isMaintenanceModeEnabled()) {
+ return
Collections.unmodifiableMap(_allLiveInstanceExcludeTimedOutForMaintenance);
+ }
+
return _allLiveInstanceCache.getPropertyMap();
}
diff --git
a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/AbstractRebalancer.java
b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/AbstractRebalancer.java
index 51158cb91..160e4eda6 100644
---
a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/AbstractRebalancer.java
+++
b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/AbstractRebalancer.java
@@ -104,7 +104,7 @@ public abstract class AbstractRebalancer<T extends
BaseControllerDataProvider> i
List<String> preferenceList = getPreferenceList(partition, idealState,
Collections.unmodifiableSet(cache.getAssignableLiveInstances().keySet()));
Map<String, String> bestStateForPartition =
-
computeBestPossibleStateForPartition(cache.getAssignableLiveInstances().keySet(),
+
computeBestPossibleStateForPartition(cache.getLiveInstances().keySet(),
stateModelDef,
preferenceList, currentStateOutput,
disabledInstancesForPartition, idealState,
cache.getClusterConfig(), partition,
diff --git
a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/DelayedAutoRebalancer.java
b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/DelayedAutoRebalancer.java
index 56979d2aa..252b63255 100644
---
a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/DelayedAutoRebalancer.java
+++
b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/DelayedAutoRebalancer.java
@@ -19,7 +19,6 @@ package org.apache.helix.controller.rebalancer;
* under the License.
*/
-import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -33,7 +32,6 @@ import java.util.Set;
import org.apache.helix.HelixDefinedState;
import org.apache.helix.api.config.StateTransitionThrottleConfig;
-import org.apache.helix.constants.InstanceConstants;
import
org.apache.helix.controller.dataproviders.ResourceControllerDataProvider;
import
org.apache.helix.controller.rebalancer.constraint.MonitoredAbnormalResolver;
import org.apache.helix.controller.rebalancer.util.DelayedRebalanceUtil;
@@ -55,8 +53,6 @@ import org.slf4j.LoggerFactory;
*/
public class DelayedAutoRebalancer extends
AbstractRebalancer<ResourceControllerDataProvider> {
private static final Logger LOG =
LoggerFactory.getLogger(DelayedAutoRebalancer.class);
- public static ImmutableSet<String>
INSTANCE_OPERATION_TO_EXCLUDE_FROM_ASSIGNMENT =
- ImmutableSet.of(InstanceConstants.InstanceOperation.EVACUATE.name());
@Override
public IdealState computeNewIdealState(String resourceName,
@@ -160,14 +156,8 @@ public class DelayedAutoRebalancer extends
AbstractRebalancer<ResourceController
stateCountMap, maxPartition);
List<String> allNodeList = new ArrayList<>(assignableNodes);
+ List<String> liveEnabledAssignableNodeList = new
ArrayList<>(assignableLiveEnabledNodes);
- // TODO: Currently we have 2 groups of instances and compute preference
list twice and merge.
- // Eventually we want to have exclusive groups of instance for different
instance tag.
- List<String> liveEnabledAssignableNodeList = new ArrayList<>(
- // We will not assign partitions to instances with EVACUATE
InstanceOperation.
- DelayedRebalanceUtil.filterOutEvacuatingInstances(
- clusterData.getAssignableInstanceConfigMap(),
- assignableLiveEnabledNodes));
// sort node lists to ensure consistent preferred assignments
Collections.sort(allNodeList);
Collections.sort(liveEnabledAssignableNodeList);
@@ -276,7 +266,9 @@ public class DelayedAutoRebalancer extends
AbstractRebalancer<ResourceController
cache.getDisabledInstancesForPartition(resource.getResourceName(),
partition.toString());
List<String> preferenceList = getPreferenceList(partition, idealState,
activeNodes);
Map<String, String> bestStateForPartition =
- computeBestPossibleStateForPartition(liveNodes, stateModelDef,
preferenceList,
+ // We use cache.getLiveInstances().keySet() to make sure we
gracefully handle n -> n + 1 replicas if possible
+ // when the one of the current nodes holding the replica is no
longer considered assignable. (ex: EVACUATE)
+
computeBestPossibleStateForPartition(cache.getLiveInstances().keySet(),
stateModelDef, preferenceList,
currentStateOutput, disabledInstancesForPartition, idealState,
clusterConfig,
partition, cache.getAbnormalStateResolver(stateModelDefName),
cache);
@@ -404,7 +396,7 @@ public class DelayedAutoRebalancer extends
AbstractRebalancer<ResourceController
// If the load-balance finishes (all replica are migrated to new
instances),
// we should drop all partitions from previous assigned instances.
- if
(!currentMapWithPreferenceList.values().contains(HelixDefinedState.ERROR.name())
+ if
(!currentMapWithPreferenceList.containsValue(HelixDefinedState.ERROR.name())
&& bestPossibleStateMap.size() > numReplicas &&
readyToDrop(currentStateMap,
bestPossibleStateMap, preferenceList, combinedPreferenceList)) {
for (int i = 0; i < combinedPreferenceList.size() - numReplicas; i++) {
diff --git
a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/util/DelayedRebalanceUtil.java
b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/util/DelayedRebalanceUtil.java
index f4fb26541..2796064db 100644
---
a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/util/DelayedRebalanceUtil.java
+++
b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/util/DelayedRebalanceUtil.java
@@ -85,28 +85,28 @@ public class DelayedRebalanceUtil {
}
/**
- * @return all active nodes (live nodes not marked as evacuate plus
offline-yet-active nodes)
+ * @return all active nodes (live nodes plus offline-yet-active nodes)
* while considering cluster delay rebalance configurations.
*/
public static Set<String> getActiveNodes(Set<String> allNodes, Set<String>
liveEnabledNodes,
Map<String, Long> instanceOfflineTimeMap, Set<String> liveNodes,
Map<String, InstanceConfig> instanceConfigMap, ClusterConfig
clusterConfig) {
if (!isDelayRebalanceEnabled(clusterConfig)) {
- return filterOutEvacuatingInstances(instanceConfigMap, liveEnabledNodes);
+ return liveEnabledNodes;
}
return getActiveNodes(allNodes, liveEnabledNodes, instanceOfflineTimeMap,
liveNodes,
instanceConfigMap, clusterConfig.getRebalanceDelayTime(),
clusterConfig);
}
/**
- * @return all active nodes (live nodes not marked as evacuate plus
offline-yet-active nodes)
+ * @return all active nodes (live nodes plus offline-yet-active nodes)
* while considering cluster delay rebalance configurations.
*/
public static Set<String> getActiveNodes(Set<String> allNodes, IdealState
idealState,
Set<String> liveEnabledNodes, Map<String, Long> instanceOfflineTimeMap,
Set<String> liveNodes,
Map<String, InstanceConfig> instanceConfigMap, long delay, ClusterConfig
clusterConfig) {
if (!isDelayRebalanceEnabled(idealState, clusterConfig)) {
- return filterOutEvacuatingInstances(instanceConfigMap, liveEnabledNodes);
+ return liveEnabledNodes;
}
return getActiveNodes(allNodes, liveEnabledNodes, instanceOfflineTimeMap,
liveNodes,
instanceConfigMap, delay, clusterConfig);
@@ -128,17 +128,7 @@ public class DelayedRebalanceUtil {
activeNodes.add(ins);
}
}
- // TODO: change this after merging operation and helix-enable field.
- return filterOutEvacuatingInstances(instanceConfigMap, activeNodes);
- }
-
- public static Set<String> filterOutEvacuatingInstances(Map<String,
InstanceConfig> instanceConfigMap,
- Set<String> nodes) {
- return nodes.stream()
- .filter(instance -> (instanceConfigMap.get(instance) != null &&
!instanceConfigMap.get(instance)
- .getInstanceOperation()
- .equals(InstanceConstants.InstanceOperation.EVACUATE.name())))
- .collect(Collectors.toSet());
+ return activeNodes;
}
/**
diff --git
a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/WagedRebalancer.java
b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/WagedRebalancer.java
index 4c4f9cf94..b0527e5e8 100644
---
a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/WagedRebalancer.java
+++
b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/WagedRebalancer.java
@@ -401,10 +401,7 @@ public class WagedRebalancer implements
StatefulRebalancer<ResourceControllerDat
RebalanceAlgorithm algorithm) throws HelixRebalanceException {
// the "real" live nodes at the time
- // TODO: Move evacuation into BaseControllerDataProvider assignableNode
logic.
- final Set<String> enabledLiveInstances =
DelayedRebalanceUtil.filterOutEvacuatingInstances(
- clusterData.getAssignableInstanceConfigMap(),
- clusterData.getAssignableEnabledLiveInstances());
+ final Set<String> enabledLiveInstances =
clusterData.getAssignableEnabledLiveInstances();
if (activeNodes.equals(enabledLiveInstances) ||
!requireRebalanceOverwrite(clusterData, currentResourceAssignment)) {
// no need for additional process, return the current resource assignment
@@ -626,10 +623,7 @@ public class WagedRebalancer implements
StatefulRebalancer<ResourceControllerDat
String resourceName = resourceAssignment.getResourceName();
IdealState currentIdealState = clusterData.getIdealState(resourceName);
- // TODO: Move evacuation into BaseControllerDataProvider assignableNode
logic.
- Set<String> enabledLiveInstances =
DelayedRebalanceUtil.filterOutEvacuatingInstances(
- clusterData.getAssignableInstanceConfigMap(),
- clusterData.getAssignableEnabledLiveInstances());
+ Set<String> enabledLiveInstances =
clusterData.getAssignableEnabledLiveInstances();
int numReplica =
currentIdealState.getReplicaCount(enabledLiveInstances.size());
int minActiveReplica =
DelayedRebalanceUtil.getMinActiveReplica(ResourceConfig
diff --git
a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java
b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java
index aa94a0244..c5303cdd2 100644
--- a/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java
+++ b/helix-core/src/main/java/org/apache/helix/manager/zk/ZKHelixAdmin.java
@@ -121,6 +121,8 @@ public class ZKHelixAdmin implements HelixAdmin {
private static final int DEFAULT_SUPERCLUSTER_REPLICA = 3;
private static final ImmutableSet<String>
ALLOWED_INSTANCE_OPERATIONS_FOR_ADD_INSTANCE =
ImmutableSet.of("", InstanceConstants.InstanceOperation.SWAP_IN.name());
+ private static final ImmutableSet<String>
INSTANCE_OPERATION_TO_EXCLUDE_FROM_ASSIGNMENT =
+ ImmutableSet.of(InstanceConstants.InstanceOperation.EVACUATE.name());
private final RealmAwareZkClient _zkClient;
private final ConfigAccessor _configAccessor;
@@ -840,7 +842,7 @@ public class ZKHelixAdmin implements HelixAdmin {
public boolean isReadyForPreparingJoiningCluster(String clusterName, String
instanceName) {
if (!instanceHasFullAutoCurrentStateOrMessage(clusterName, instanceName)) {
InstanceConfig config = getInstanceConfig(clusterName, instanceName);
- return config != null &&
DelayedAutoRebalancer.INSTANCE_OPERATION_TO_EXCLUDE_FROM_ASSIGNMENT.contains(
+ return config != null &&
INSTANCE_OPERATION_TO_EXCLUDE_FROM_ASSIGNMENT.contains(
config.getInstanceOperation());
}
return false;
diff --git
a/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java
b/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java
index 713944e98..0019ea83c 100644
---
a/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java
+++
b/helix-core/src/test/java/org/apache/helix/integration/rebalancer/TestInstanceOperation.java
@@ -262,7 +262,17 @@ public class TestInstanceOperation extends ZkTestBase {
// Drop semi-auto DBs
_gSetupTool.dropResourceFromCluster(CLUSTER_NAME, semiAutoDB);
Assert.assertTrue(_clusterVerifier.verifyByPolling());
- }
+
+ // Disable, stop, and drop the instance from the cluster.
+ _gSetupTool.getClusterManagementTool().enableInstance(CLUSTER_NAME,
instanceToEvacuate, false);
+ _participants.get(0).syncStop();
+ removeOfflineOrDisabledOrSwapInInstances();
+
+ // Compare the current ev with the previous one, it should be exactly the
same since the baseline should not change
+ // after the instance is dropped.
+ Assert.assertTrue(_clusterVerifier.verifyByPolling());
+ Assert.assertEquals(getEVs(), assignment);
+}
@Test(dependsOnMethods = "testEvacuate")
public void testRevertEvacuation() throws Exception {
@@ -1248,7 +1258,7 @@ public class TestInstanceOperation extends ZkTestBase {
Assert.assertTrue(getParticipantsInEv(assignment.get(resource)).contains(instanceToEvacuate));
}
- Assert.assertTrue(_clusterVerifier.verifyByPolling());
+ Assert.assertTrue(_bestPossibleClusterVerifier.verifyByPolling());
// exit MM
_gSetupTool.getClusterManagementTool()
diff --git
a/helix-rest/src/test/java/org/apache/helix/rest/server/TestPerInstanceAccessor.java
b/helix-rest/src/test/java/org/apache/helix/rest/server/TestPerInstanceAccessor.java
index 48343f8d0..355d5d101 100644
---
a/helix-rest/src/test/java/org/apache/helix/rest/server/TestPerInstanceAccessor.java
+++
b/helix-rest/src/test/java/org/apache/helix/rest/server/TestPerInstanceAccessor.java
@@ -527,18 +527,12 @@ public class TestPerInstanceAccessor extends
AbstractTestClass {
Assert.assertFalse((boolean) responseMap.get("successful"));
// test isEvacuateFinished on instance with EVACUATE but has currentState
- // Enable persist best possible assignment for cluster verifier
- ConfigAccessor configAccessor = new ConfigAccessor(_gZkClient);
- ClusterConfig clusterConfig =
configAccessor.getClusterConfig(CLUSTER_NAME);
- clusterConfig.setPersistBestPossibleAssignment(true);
- configAccessor.setClusterConfig(CLUSTER_NAME, clusterConfig);
- Set<String> resources = _resourcesMap.get(CLUSTER_NAME);
- ZkHelixClusterVerifier clusterVerifier = new
StrictMatchExternalViewVerifier.Builder(CLUSTER_NAME).setZkAddr(ZK_ADDR)
- .setDeactivatedNodeAwareness(true)
- .setResources(resources)
- .setWaitTillVerify(TestHelper.DEFAULT_REBALANCE_PROCESSING_WAIT_TIME)
- .build();
+ // Put the cluster in MM so no assignment is calculated
+ _gSetupTool.getClusterManagementTool()
+ .enableMaintenanceMode(CLUSTER_NAME, true, "Change resource to
full-auto");
+
// Make the DBs FULL_AUTO and wait because EVACUATE is only supported for
FULL_AUTO resources
+ Set<String> resources = _resourcesMap.get(CLUSTER_NAME);
for (String resource : resources) {
IdealState idealState =
_gSetupTool.getClusterManagementTool().getResourceIdealState(CLUSTER_NAME,
resource);
@@ -548,8 +542,6 @@ public class TestPerInstanceAccessor extends
AbstractTestClass {
_gSetupTool.getClusterManagementTool().setResourceIdealState(CLUSTER_NAME,
resource, idealState);
}
- Assert.assertTrue(clusterVerifier.verifyByPolling());
-
new
JerseyUriRequestBuilder("clusters/{}/instances/{}?command=setInstanceOperation&instanceOperation=EVACUATE")
.format(CLUSTER_NAME, INSTANCE_NAME).post(this, entity);
instanceConfig = _configAccessor.getInstanceConfig(CLUSTER_NAME,
INSTANCE_NAME);
@@ -558,9 +550,10 @@ public class TestPerInstanceAccessor extends
AbstractTestClass {
Response response = new
JerseyUriRequestBuilder("clusters/{}/instances/{}?command=isEvacuateFinished")
.format(CLUSTER_NAME, INSTANCE_NAME).post(this, entity);
- Map<String, Boolean> evacuateFinishedresult =
OBJECT_MAPPER.readValue(response.readEntity(String.class), Map.class);
+ Map<String, Boolean> evacuateFinishedResult =
OBJECT_MAPPER.readValue(response.readEntity(String.class), Map.class);
Assert.assertEquals(response.getStatus(),
Response.Status.OK.getStatusCode());
- Assert.assertFalse(evacuateFinishedresult.get("successful"));
+ // Returns false because the node still contains full-auto resources
+ Assert.assertFalse(evacuateFinishedResult.get("successful"));
// Make all resources SEMI_AUTO again
for (String resource : resources) {
@@ -572,8 +565,16 @@ public class TestPerInstanceAccessor extends
AbstractTestClass {
_gSetupTool.getClusterManagementTool().setResourceIdealState(CLUSTER_NAME,
resource, idealState);
}
- // Wait for the cluster to be stable again
- Assert.assertTrue(clusterVerifier.verifyByPolling());
+ // Exit MM
+ _gSetupTool.getClusterManagementTool()
+ .enableMaintenanceMode(CLUSTER_NAME, false, "Change resource to
full-auto");
+
+ // Because the resources are now all semi-auto, is EvacuateFinished should
return true
+ response = new
JerseyUriRequestBuilder("clusters/{}/instances/{}?command=isEvacuateFinished")
+ .format(CLUSTER_NAME, INSTANCE_NAME).post(this, entity);
+ evacuateFinishedResult =
OBJECT_MAPPER.readValue(response.readEntity(String.class), Map.class);
+ Assert.assertEquals(response.getStatus(),
Response.Status.OK.getStatusCode());
+ Assert.assertTrue(evacuateFinishedResult.get("successful"));
// test isEvacuateFinished on instance with EVACUATE and no currentState
// Create new instance so no currentState or messages assigned to it
@@ -592,9 +593,9 @@ public class TestPerInstanceAccessor extends
AbstractTestClass {
response = new
JerseyUriRequestBuilder("clusters/{}/instances/{}?command=isEvacuateFinished")
.format(CLUSTER_NAME, test_instance_name).post(this, entity);
- evacuateFinishedresult =
OBJECT_MAPPER.readValue(response.readEntity(String.class), Map.class);
+ evacuateFinishedResult =
OBJECT_MAPPER.readValue(response.readEntity(String.class), Map.class);
Assert.assertEquals(response.getStatus(),
Response.Status.OK.getStatusCode());
- Assert.assertTrue(evacuateFinishedresult.get("successful"));
+ Assert.assertTrue(evacuateFinishedResult.get("successful"));
System.out.println("End test :" + TestHelper.getTestMethodName());
}