/*
* 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.cluster.routing.allocation;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.routing.allocation.decider.Decision;
import org.elasticsearch.cluster.routing.allocation.decider.Decision.Type;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
/**
* Unit tests for the {@link MoveDecision} class.
*/
public class MoveDecisionTests extends ESTestCase {
public void testCachedDecisions() {
// cached stay decision
MoveDecision stay1 = MoveDecision.stay(null);
MoveDecision stay2 = MoveDecision.stay(null);
assertSame(stay1, stay2); // not in explain mode, so should use cached decision
stay1 = MoveDecision.stay(Decision.YES);
stay2 = MoveDecision.stay(Decision.YES);
assertNotSame(stay1, stay2);
// cached cannot move decision
stay1 = MoveDecision.cannotRemain(Decision.NO, AllocationDecision.NO, null, null);
stay2 = MoveDecision.cannotRemain(Decision.NO, AllocationDecision.NO, null, null);
assertSame(stay1, stay2);
// final decision is YES, so shouldn't use cached decision
DiscoveryNode node1 = new DiscoveryNode("node1", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
stay1 = MoveDecision.cannotRemain(Decision.NO, AllocationDecision.YES, node1, null);
stay2 = MoveDecision.cannotRemain(Decision.NO, AllocationDecision.YES, node1, null);
assertNotSame(stay1, stay2);
assertEquals(stay1.getTargetNode(), stay2.getTargetNode());
// final decision is NO, but in explain mode, so shouldn't use cached decision
stay1 = MoveDecision.cannotRemain(Decision.NO, AllocationDecision.NO, null, new ArrayList<>());
stay2 = MoveDecision.cannotRemain(Decision.NO, AllocationDecision.NO, null, new ArrayList<>());
assertNotSame(stay1, stay2);
assertSame(stay1.getAllocationDecision(), stay2.getAllocationDecision());
assertNotNull(stay1.getExplanation());
assertEquals(stay1.getExplanation(), stay2.getExplanation());
}
public void testStayDecision() {
MoveDecision stay = MoveDecision.stay(Decision.YES);
assertTrue(stay.canRemain());
assertFalse(stay.forceMove());
assertTrue(stay.isDecisionTaken());
assertNull(stay.getNodeDecisions());
assertEquals(AllocationDecision.NO_ATTEMPT, stay.getAllocationDecision());
stay = MoveDecision.stay(Decision.YES);
assertTrue(stay.canRemain());
assertFalse(stay.forceMove());
assertTrue(stay.isDecisionTaken());
assertNull(stay.getNodeDecisions());
assertEquals(AllocationDecision.NO_ATTEMPT, stay.getAllocationDecision());
}
public void testDecisionWithNodeExplanations() {
DiscoveryNode node1 = new DiscoveryNode("node1", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
DiscoveryNode node2 = new DiscoveryNode("node2", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
Decision nodeDecision = randomFrom(Decision.NO, Decision.THROTTLE, Decision.YES);
List<NodeAllocationResult> nodeDecisions = new ArrayList<>();
nodeDecisions.add(new NodeAllocationResult(node1, nodeDecision, 2));
nodeDecisions.add(new NodeAllocationResult(node2, nodeDecision, 1));
MoveDecision decision = MoveDecision.cannotRemain(Decision.NO, AllocationDecision.NO, null, nodeDecisions);
assertNotNull(decision.getAllocationDecision());
assertNotNull(decision.getExplanation());
assertNotNull(decision.getNodeDecisions());
assertEquals(2, decision.getNodeDecisions().size());
// both nodes have the same decision type but node2 has a higher weight ranking, so node2 comes first
assertEquals("node2", decision.getNodeDecisions().iterator().next().getNode().getId());
decision = MoveDecision.cannotRemain(Decision.NO, AllocationDecision.YES, node2, null);
assertEquals("node2", decision.getTargetNode().getId());
}
public void testSerialization() throws IOException {
List<NodeAllocationResult> nodeDecisions = new ArrayList<>();
DiscoveryNode node1 = new DiscoveryNode("node1", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
DiscoveryNode node2 = new DiscoveryNode("node2", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT);
Type finalDecision = randomFrom(Type.values());
DiscoveryNode assignedNode = finalDecision == Type.YES ? node1 : null;
nodeDecisions.add(new NodeAllocationResult(node1, Decision.NO, 2));
nodeDecisions.add(new NodeAllocationResult(node2, finalDecision == Type.YES ? Decision.YES :
randomFrom(Decision.NO, Decision.THROTTLE, Decision.YES), 1));
MoveDecision moveDecision = MoveDecision.cannotRemain(Decision.NO, AllocationDecision.fromDecisionType(finalDecision),
assignedNode, nodeDecisions);
BytesStreamOutput output = new BytesStreamOutput();
moveDecision.writeTo(output);
MoveDecision readDecision = new MoveDecision(output.bytes().streamInput());
assertEquals(moveDecision.canRemain(), readDecision.canRemain());
assertEquals(moveDecision.getExplanation(), readDecision.getExplanation());
assertEquals(moveDecision.forceMove(), readDecision.forceMove());
assertEquals(moveDecision.getNodeDecisions().size(), readDecision.getNodeDecisions().size());
assertEquals(moveDecision.getTargetNode(), readDecision.getTargetNode());
assertEquals(moveDecision.getAllocationDecision(), readDecision.getAllocationDecision());
// node2 should have the highest sort order
assertEquals("node2", readDecision.getNodeDecisions().iterator().next().getNode().getId());
}
}