/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package functionaltests.nodestate; import static functionaltests.utils.RMTHelper.log; import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.*; import org.junit.Test; import org.objectweb.proactive.api.PAFuture; import org.objectweb.proactive.core.ProActiveTimeoutException; import org.objectweb.proactive.core.node.Node; import org.ow2.proactive.resourcemanager.common.NodeState; import org.ow2.proactive.resourcemanager.common.event.RMEventType; import org.ow2.proactive.resourcemanager.common.event.RMNodeEvent; import org.ow2.proactive.resourcemanager.frontend.ResourceManager; import org.ow2.proactive.utils.NodeSet; import functionaltests.utils.RMFunctionalTest; /** * This class tests different nodes states changes and their related Events launched by RMMonitoring * It tests Nodes removal mechanism (non preemptively method) too. * Nodes states changes can be : * * free -> busy, and busy -> free (test 1) * give back to RM a node already free (test 2) * busy -> toRelease , and toRelease -> removed (test 3) * busy -> down (test 4) * free -> down (test 5) * toRelease -> down, and down -> removed(test 6) * free -> removed (test 7) * * It tests 'node added' event too, during deployment */ public class TestNodesStates extends RMFunctionalTest { @Test public void testManyStatesChanges() throws Exception { ResourceManager resourceManager = rmHelper.getResourceManager(); int totalNodeNumber = 5; rmHelper.createNodeSource("TestNodesStates", totalNodeNumber); //---------------------------------------------------------- // Book all nodes deployed by descriptor (user action) // verify that there are no free nodes left, // and give back to RM log("Test 1"); NodeSet nodes = resourceManager.getAtMostNodes(totalNodeNumber, null); PAFuture.waitFor(nodes); assertEquals(totalNodeNumber, nodes.size()); assertEquals(0, resourceManager.getState().getFreeNodesNumber()); for (int i = 0; i < totalNodeNumber; i++) { RMNodeEvent evt = rmHelper.waitForNodeEvent(RMEventType.NODE_STATE_CHANGED, nodes.get(i).getNodeInformation().getURL()); assertEquals(NodeState.BUSY, evt.getNodeState()); checkEvent(evt, nodes.get(i)); } //for next test Node n = nodes.get(0); resourceManager.releaseNodes(nodes); for (int i = 0; i < totalNodeNumber; i++) { RMNodeEvent evt = rmHelper.waitForNodeEvent(RMEventType.NODE_STATE_CHANGED, nodes.get(i).getNodeInformation().getURL()); assertEquals(NodeState.FREE, evt.getNodeState()); checkEvent(evt, nodes.get(i)); } //---------------------------------------------------------- //give back a node already given back (i.e; node already free) //this action causes nothing(nor increasing free nodes number, nor generation of any event) log("Test 2"); resourceManager.releaseNode(n); boolean timeouted = false; try { rmHelper.waitForNodeEvent(RMEventType.NODE_STATE_CHANGED, n.getNodeInformation().getURL(), 4000); } catch (ProActiveTimeoutException e) { timeouted = true; } assertTrue(timeouted); assertEquals(totalNodeNumber, resourceManager.getState().getFreeNodesNumber()); //---------------------------------------------------------- // Book all nodes deployed by descriptor // Test admin action : Remove a node from the RM (non preemptively), // node is busy, so becomes in "toRelease" state // user give back to RM the "toRelease" node, node is now removed log("Test 3"); nodes = resourceManager.getAtMostNodes(totalNodeNumber, null); PAFuture.waitFor(nodes); for (int i = 0; i < totalNodeNumber; i++) { RMNodeEvent evt = rmHelper.waitForAnyNodeEvent(RMEventType.NODE_STATE_CHANGED); assertEquals(NodeState.BUSY, evt.getNodeState()); } n = nodes.remove(0); //put node in "To Release" state resourceManager.removeNode(n.getNodeInformation().getURL(), false); //check that node toRelease event has been thrown RMNodeEvent evt = rmHelper.waitForNodeEvent(RMEventType.NODE_STATE_CHANGED, n.getNodeInformation().getURL()); assertEquals(NodeState.TO_BE_REMOVED, evt.getNodeState()); //node is in "ToRelease" state, so always handled by RM assertEquals(totalNodeNumber, resourceManager.getState().getTotalNodesNumber()); //user give back the node, so node is now removed resourceManager.releaseNode(n); assertEquals(totalNodeNumber - 1, resourceManager.getState().getTotalNodesNumber()); assertEquals(0, resourceManager.getState().getFreeNodesNumber()); rmHelper.waitForNodeEvent(RMEventType.NODE_REMOVED, n.getNodeInformation().getURL()); //---------------------------------------------------------- // nodes are always in busy state // kill JVM of a node (simulate a fallen JVM or broken connection, i.e down node) // node must detected down by RM log("Test 4"); n = nodes.get(0); Node n2 = nodes.get(1); //for next test try { n.getProActiveRuntime().killNode(n.getNodeInformation().getName()); } catch (Exception e) { e.printStackTrace(); } evt = rmHelper.waitForNodeEvent(RMEventType.NODE_STATE_CHANGED, n.getNodeInformation().getURL()); assertEquals(NodeState.DOWN, evt.getNodeState()); checkEvent(evt, n); resourceManager.releaseNodes(nodes); // we should get 4 FREE events for (int i = 0; i < totalNodeNumber - 2; i++) { evt = rmHelper.waitForAnyNodeEvent(RMEventType.NODE_STATE_CHANGED); assertEquals(NodeState.FREE, evt.getNodeState()); } //two nodes killed, but the detected down is in RM down nodes list //( down nodes are in total nodes count) assertEquals(totalNodeNumber - 1, resourceManager.getState().getTotalNodesNumber()); assertEquals(totalNodeNumber - 2, resourceManager.getState().getFreeNodesNumber()); //---------------------------------------------------------- // nodes left are in free state // kill JVM of a free node // node must detected down by RM log("Test 5"); try { n2.getProActiveRuntime().killNode(n2.getNodeInformation().getName()); } catch (Exception e) { e.printStackTrace(); } evt = rmHelper.waitForNodeEvent(RMEventType.NODE_STATE_CHANGED, n2.getNodeInformation().getURL()); assertEquals(NodeState.DOWN, evt.getNodeState()); assertEquals(totalNodeNumber - 1, resourceManager.getState().getTotalNodesNumber()); assertEquals(totalNodeNumber - 3, resourceManager.getState().getFreeNodesNumber()); //---------------------------------------------------------- // book nodes, put one node in "toRelease" state, // then kill its JVM, // node must detected down by RM log("Test 6"); nodes = resourceManager.getAtMostNodes(totalNodeNumber - 3, null); PAFuture.waitFor(nodes); for (int i = 0; i < totalNodeNumber - 3; i++) { evt = rmHelper.waitForAnyNodeEvent(RMEventType.NODE_STATE_CHANGED); assertEquals(NodeState.BUSY, evt.getNodeState()); } n = nodes.get(0); n2 = nodes.get(1); //for next test //put node in "To Release" state resourceManager.removeNode(n.getNodeInformation().getURL(), false); evt = rmHelper.waitForNodeEvent(RMEventType.NODE_STATE_CHANGED, n.getNodeInformation().getURL()); assertEquals(NodeState.TO_BE_REMOVED, evt.getNodeState()); log("Test 6 Bis"); //kill the node try { n.getProActiveRuntime().killNode(n.getNodeInformation().getName()); } catch (Exception e) { e.printStackTrace(); } evt = rmHelper.waitForNodeEvent(RMEventType.NODE_STATE_CHANGED, n.getNodeInformation().getURL()); assertEquals(NodeState.DOWN, evt.getNodeState()); assertEquals(totalNodeNumber - 1, resourceManager.getState().getTotalNodesNumber()); assertEquals(0, resourceManager.getState().getFreeNodesNumber()); for (Node node : nodes) { log("Taken node: " + node.getNodeInformation().getURL()); } // we have 2 nodes: 11 busy and one still down resourceManager.releaseNodes(nodes); for (int i = 0; i < 1; i++) { evt = rmHelper.waitForAnyNodeEvent(RMEventType.NODE_STATE_CHANGED); assertEquals(NodeState.FREE, evt.getNodeState()); } assertEquals(totalNodeNumber - 1, resourceManager.getState().getTotalNodesNumber()); assertEquals(totalNodeNumber - 4, resourceManager.getState().getFreeNodesNumber()); //admin removes again the node, ok he already asked this removal when node n was busy //choice here is advert admin that node has fallen (not hiding the down node event), //rather than automatically remove it resourceManager.removeNode(n.getNodeInformation().getURL(), false); //check that node removed event has been received rmHelper.waitForNodeEvent(RMEventType.NODE_REMOVED, n.getNodeInformation().getURL()); assertEquals(totalNodeNumber - 2, resourceManager.getState().getTotalNodesNumber()); assertEquals(totalNodeNumber - 4, resourceManager.getState().getFreeNodesNumber()); //---------------------------------------------------------- // Remove a free node, // log("Test 7"); resourceManager.removeNode(n2.getNodeInformation().getURL(), false); //check that node removed event has been received rmHelper.waitForNodeEvent(RMEventType.NODE_REMOVED, n2.getNodeInformation().getURL()); assertEquals(totalNodeNumber - 3, resourceManager.getState().getTotalNodesNumber()); assertEquals(totalNodeNumber - 5, resourceManager.getState().getFreeNodesNumber()); log("End of test"); } private void checkEvent(RMNodeEvent event, Node node) { assertEquals(node.getNodeInformation().getURL(), event.getNodeUrl()); assertThat(event.getNodeInfo(), containsString(event.getNodeUrl())); assertThat(event.getNodeInfo(), containsString(event.getNodeProvider())); assertThat(event.getNodeInfo(), containsString(event.getHostName())); } }