/* * 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.rm; import static functionaltests.utils.SchedulerTHelper.log; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.net.URI; import java.util.AbstractMap; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.objectweb.proactive.api.PAActiveObject; import org.objectweb.proactive.api.PAFuture; import org.objectweb.proactive.core.config.CentralPAPropertyRepository; import org.ow2.proactive.authentication.crypto.CredData; import org.ow2.proactive.authentication.crypto.Credentials; import org.ow2.proactive.resourcemanager.common.event.RMEventType; import org.ow2.proactive.resourcemanager.core.properties.PAResourceManagerProperties; import org.ow2.proactive.resourcemanager.frontend.ResourceManager; import org.ow2.proactive.scheduler.core.properties.PASchedulerProperties; import org.ow2.proactive.scheduler.core.rmproxies.PerUserConnectionRMProxiesManager; import org.ow2.proactive.scheduler.core.rmproxies.RMProxiesManager; import org.ow2.proactive.scheduler.core.rmproxies.RMProxy; import org.ow2.proactive.scheduler.core.rmproxies.SingleConnectionRMProxiesManager; import org.ow2.proactive.utils.Criteria; import org.ow2.proactive.utils.NodeSet; import functionaltests.monitor.RMMonitorEventReceiver; import functionaltests.monitor.RMMonitorsHandler; import functionaltests.utils.*; public class TestRMProxyRebind extends MultipleRMTBase { private static final int NODES_NUMBER = 3; private Credentials schedulerProxyCredentials; private TestRM helper1; private TestRM helper2; private int pnpPort1; private int jmxPort1; private int pnpPort2; private int jmxPort2; private ResourceManager rm1; private ResourceManager rm2; private List<RMMonitorEventReceiver> eventReceivers = new ArrayList<>(); private RMMonitorsHandler monitorsHandler1; private RMMonitorsHandler monitorsHandler2; private List<TestNode> testNodes = new ArrayList<>(); @BeforeClass public static void setUp() throws Exception { if (TestScheduler.isStarted()) { SchedulerTHelper.log("Killing previous scheduler."); TestScheduler.kill(); } initConfigs(); } @Before public void createRMs() throws Exception { schedulerProxyCredentials = Credentials.getCredentials(PASchedulerProperties.getAbsolutePath(PASchedulerProperties.RESOURCE_MANAGER_CREDS.getValueAsString())); helper1 = new TestRM(); helper2 = new TestRM(); pnpPort1 = CentralPAPropertyRepository.PA_RMI_PORT.getValue() + 1; jmxPort1 = PAResourceManagerProperties.RM_JMX_PORT.getValueAsInt() + 1; pnpPort2 = CentralPAPropertyRepository.PA_RMI_PORT.getValue() + 2; jmxPort2 = PAResourceManagerProperties.RM_JMX_PORT.getValueAsInt() + 2; helper1.start(config1.getAbsolutePath(), pnpPort1, PAResourceManagerProperties.RM_JMX_PORT.getCmdLine() + jmxPort1); Credentials connectedUserCreds = Credentials.createCredentials(new CredData(CredData.parseLogin(TestUsers.DEMO.username), CredData.parseDomain(TestUsers.DEMO.username), TestUsers.DEMO.password), helper1.getAuth().getPublicKey()); Map.Entry<RMMonitorsHandler, RMMonitorEventReceiver> entry1 = connectToRM(helper1.getUrl(), connectedUserCreds); monitorsHandler1 = entry1.getKey(); rm1 = entry1.getValue(); testNodes.addAll(RMTHelper.addNodesToDefaultNodeSource(NODES_NUMBER, new ArrayList<String>(), rm1, monitorsHandler1)); helper2.start(config2.getAbsolutePath(), pnpPort2, PAResourceManagerProperties.RM_JMX_PORT.getCmdLine() + jmxPort2); Map.Entry<RMMonitorsHandler, RMMonitorEventReceiver> entry2 = connectToRM(helper2.getUrl(), connectedUserCreds); monitorsHandler2 = entry2.getKey(); rm2 = entry2.getValue(); testNodes.addAll(RMTHelper.addNodesToDefaultNodeSource(NODES_NUMBER, new ArrayList<String>(), rm2, monitorsHandler2)); checkFreeNodes(rm1, NODES_NUMBER); checkFreeNodes(rm2, NODES_NUMBER); } @After public void stopRMs() throws Exception { if (rm1 != null) { PAFuture.waitFor(rm1.shutdown(true)); } if (rm2 != null) { PAFuture.waitFor(rm2.shutdown(true)); } helper1.kill(); helper2.kill(); for (TestNode node : testNodes) { try { node.kill(); } catch (Exception ignored) { } } for (RMMonitorEventReceiver receiver : eventReceivers) { try { PAActiveObject.terminateActiveObject(receiver, true); } catch (Exception ignored) { } } } @Test public void testRMProxyRebindSingle() throws Exception { log("\n Test with single connection \n"); testRebind(new URI(helper1.getUrl()), new URI(helper2.getUrl()), rm1, rm2, monitorsHandler1, monitorsHandler2, true); } @Test public void testRMProxyRebindPerUser() throws Exception { log("\n Test with per-user connection \n"); testRebind(new URI(helper1.getUrl()), new URI(helper2.getUrl()), rm1, rm2, monitorsHandler1, monitorsHandler2, false); } private Map.Entry<RMMonitorsHandler, RMMonitorEventReceiver> connectToRM(String rmUrl, Credentials creds) throws Exception { RMMonitorsHandler monitorsHandler1 = new RMMonitorsHandler(); /** create event receiver then turnActive to avoid deepCopy of MonitorsHandler object * (shared instance between event receiver and static helpers). */ RMMonitorEventReceiver passiveEventReceiver = new RMMonitorEventReceiver(monitorsHandler1); RMMonitorEventReceiver receiver = PAActiveObject.turnActive(passiveEventReceiver); eventReceivers.add(receiver); receiver.init(rmUrl, creds); return new AbstractMap.SimpleImmutableEntry<RMMonitorsHandler, RMMonitorEventReceiver>(monitorsHandler1, receiver); } private void testRebind(URI rmUri1, URI rmUri2, ResourceManager rm1, ResourceManager rm2, RMMonitorsHandler monitorsHandler1, RMMonitorsHandler monitorsHandler2, boolean singleConnection) throws Exception { RMProxiesManager proxiesManager; if (singleConnection) { proxiesManager = new SingleConnectionRMProxiesManager(rmUri1, schedulerProxyCredentials); } else { proxiesManager = new PerUserConnectionRMProxiesManager(rmUri1, schedulerProxyCredentials); } Credentials user1Credentials = Credentials.createCredentials(new CredData("admin", "admin"), helper1.getAuth().getPublicKey()); RMProxy proxy1 = proxiesManager.getUserRMProxy("admin", user1Credentials); log("Get one node with RM1"); NodeSet rm1NodeSet1 = proxy1.getNodes(new Criteria(1)); waitWhenNodeSetAcquired(rm1NodeSet1, 1, monitorsHandler1); checkFreeNodes(rm1, NODES_NUMBER - 1); checkFreeNodes(rm2, NODES_NUMBER); assertEquals(NODES_NUMBER - 1, proxiesManager.getRmProxy().getState().getFreeNodesNumber()); log("Get one node with RM1"); NodeSet rm1NodeSet2 = proxy1.getNodes(new Criteria(1)); waitWhenNodeSetAcquired(rm1NodeSet2, 1, monitorsHandler1); checkFreeNodes(rm1, NODES_NUMBER - 2); checkFreeNodes(rm2, NODES_NUMBER); assertEquals(NODES_NUMBER - 2, proxiesManager.getRmProxy().getState().getFreeNodesNumber()); assertTrue(proxiesManager.getRmProxy().isActive().getBooleanValue()); log("Rebinding to " + rmUri2); proxiesManager.rebindRMProxiesManager(rmUri2); assertEquals(NODES_NUMBER, proxiesManager.getRmProxy().getState().getFreeNodesNumber()); assertTrue(proxiesManager.getRmProxy().isActive().getBooleanValue()); waitWhenNodeSetReleased(2, monitorsHandler1); log("Get one node with RM2"); NodeSet rm2NodeSet1 = proxy1.getNodes(new Criteria(1)); waitWhenNodeSetAcquired(rm2NodeSet1, 1, monitorsHandler2); checkFreeNodes(rm1, NODES_NUMBER); checkFreeNodes(rm2, NODES_NUMBER - 1); assertEquals(NODES_NUMBER - 1, proxiesManager.getRmProxy().getState().getFreeNodesNumber()); log("Get two nodes with RM2"); NodeSet rm2NodeSet2 = proxy1.getNodes(new Criteria(2)); waitWhenNodeSetAcquired(rm2NodeSet2, 2, monitorsHandler2); checkFreeNodes(rm1, NODES_NUMBER); checkFreeNodes(rm2, NODES_NUMBER - 3); assertEquals(NODES_NUMBER - 3, proxiesManager.getRmProxy().getState().getFreeNodesNumber()); log("Release one node with RM2"); proxy1.releaseNodes(rm2NodeSet1); waitWhenNodeSetReleased(1, monitorsHandler2); checkFreeNodes(rm1, NODES_NUMBER); checkFreeNodes(rm2, NODES_NUMBER - 2); assertEquals(NODES_NUMBER - 2, proxiesManager.getRmProxy().getState().getFreeNodesNumber()); log("Kill RM1"); PAFuture.waitFor(rm1.shutdown(true)); helper1.kill(); rm1 = null; assertEquals(NODES_NUMBER - 2, proxiesManager.getRmProxy().getState().getFreeNodesNumber()); assertTrue(proxiesManager.getRmProxy().isActive().getBooleanValue()); log("Release two nodes with RM2"); proxy1.releaseNodes(rm2NodeSet2); waitWhenNodeSetReleased(2, monitorsHandler2); checkFreeNodes(rm2, NODES_NUMBER); assertEquals(NODES_NUMBER, proxiesManager.getRmProxy().getState().getFreeNodesNumber()); assertTrue(proxiesManager.getRmProxy().isActive().getBooleanValue()); log("Try to release node with terminated RM1"); proxy1.releaseNodes(rm1NodeSet2); log("Try to release node with terminated RM1 one more time"); proxy1.releaseNodes(rm1NodeSet2); assertEquals(NODES_NUMBER, proxiesManager.getRmProxy().getState().getFreeNodesNumber()); assertTrue(proxiesManager.getRmProxy().isActive().getBooleanValue()); log("Terminate all proxies"); proxiesManager.terminateAllProxies(); } private void waitWhenNodeSetReleased(int nodesNumber, RMMonitorsHandler monitor) { for (int i = 0; i < nodesNumber; i++) { RMTHelper.waitForAnyNodeEvent(RMEventType.NODE_STATE_CHANGED, monitor); } } private void waitWhenNodeSetAcquired(NodeSet nodeSet, int expectedNodesNumber, RMMonitorsHandler monitor) { PAFuture.waitFor(nodeSet); assertEquals("Unexpected nodes number in NodeSet", expectedNodesNumber, nodeSet.size()); for (int i = 0; i < expectedNodesNumber; i++) { RMTHelper.waitForAnyNodeEvent(RMEventType.NODE_STATE_CHANGED, monitor); } } private void checkFreeNodes(ResourceManager rm, int expectedNumber) { assertEquals("Unexpected number of free nodes", expectedNumber, rm.getState().getFreeNodesNumber()); } }