/*
* 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.utils;
import java.io.File;
import java.io.FilenameFilter;
import java.net.URISyntaxException;
import java.security.KeyException;
import java.util.*;
import javax.security.auth.login.LoginException;
import org.objectweb.proactive.api.PAFuture;
import org.objectweb.proactive.core.config.CentralPAPropertyRepository;
import org.objectweb.proactive.core.util.ProActiveInet;
import org.objectweb.proactive.extensions.pnp.PNPConfig;
import org.ow2.proactive.authentication.crypto.CredData;
import org.ow2.proactive.authentication.crypto.Credentials;
import org.ow2.proactive.resourcemanager.authentication.RMAuthentication;
import org.ow2.proactive.resourcemanager.core.properties.PAResourceManagerProperties;
import org.ow2.proactive.resourcemanager.frontend.RMConnection;
import org.ow2.proactive.resourcemanager.frontend.ResourceManager;
import org.ow2.proactive.scheduler.common.SchedulerAuthenticationInterface;
import org.ow2.proactive.scheduler.common.SchedulerConnection;
import org.ow2.proactive.scheduler.core.properties.PASchedulerProperties;
import org.ow2.proactive.scheduler.task.utils.ForkerUtils;
import org.ow2.proactive.utils.CookieBasedProcessTreeKiller;
import org.ow2.proactive.utils.FileUtils;
public class TestScheduler {
public static final int PNP_PORT = TestRM.PA_PNP_PORT;
public static String schedulerUrl = "pnp://" + ProActiveInet.getInstance().getHostname() + ":" + PNP_PORT + "/";
public static String rmUrl;
private static Process schedulerProcess;
private static SchedulerAuthenticationInterface schedulerAuth;
private static RMAuthentication rmAuth;
private static CookieBasedProcessTreeKiller processTreeKiller;
private static SchedulerTestConfiguration startedConfiguration = SchedulerTestConfiguration.defaultConfiguration();
private static boolean isStarted = false;
public static synchronized void start(SchedulerTestConfiguration configuration) throws Exception {
kill();
cleanTMP();
startedConfiguration = configuration;
List<String> commandLine = new ArrayList<>();
commandLine.add(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java");
commandLine.add("-Djava.security.manager");
commandLine.add("-Dfile.encoding=" + System.getProperty("file.encoding"));
// commandLine.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005");
String proactiveHome = CentralPAPropertyRepository.PA_HOME.getValue();
if (!CentralPAPropertyRepository.PA_HOME.isSet()) {
proactiveHome = PAResourceManagerProperties.RM_HOME.getValueAsString();
CentralPAPropertyRepository.PA_HOME.setValue(PAResourceManagerProperties.RM_HOME.getValueAsString());
}
commandLine.add(CentralPAPropertyRepository.PA_HOME.getCmdLine() + proactiveHome);
commandLine.add(CentralPAPropertyRepository.PA_COMMUNICATION_PROTOCOL.getCmdLine() + "pnp");
commandLine.add(PNPConfig.PA_PNP_PORT.getCmdLine() + configuration.getPnpPort());
String securityPolicy = CentralPAPropertyRepository.JAVA_SECURITY_POLICY.getValue();
if (!CentralPAPropertyRepository.JAVA_SECURITY_POLICY.isSet()) {
securityPolicy = PASchedulerProperties.SCHEDULER_HOME.getValueAsString() +
"/config/security.java.policy-server";
}
commandLine.add(CentralPAPropertyRepository.JAVA_SECURITY_POLICY.getCmdLine() + securityPolicy);
String log4jConfiguration = CentralPAPropertyRepository.LOG4J.getValue();
if (!CentralPAPropertyRepository.LOG4J.isSet()) {
log4jConfiguration = SchedulerTHelper.class.getResource("/log4j-junit").toString();
}
commandLine.add(CentralPAPropertyRepository.LOG4J.getCmdLine() + log4jConfiguration);
commandLine.add(PASchedulerProperties.SCHEDULER_HOME.getCmdLine() +
PASchedulerProperties.SCHEDULER_HOME.getValueAsString());
commandLine.add(PAResourceManagerProperties.RM_HOME.getCmdLine() +
PAResourceManagerProperties.RM_HOME.getValueAsString());
String forkMethodKeyValue = System.getProperty(ForkerUtils.FORK_METHOD_KEY);
if (forkMethodKeyValue != null) {
commandLine.add("-D" + ForkerUtils.FORK_METHOD_KEY + "=" + System.getProperty(forkMethodKeyValue));
}
if (System.getProperty("proactive.test.runAsMe") != null) {
commandLine.add("-Dproactive.test.runAsMe=true");
}
//commandLine.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8765");
commandLine.add("-cp");
commandLine.add(testClasspath());
commandLine.add("-Djava.awt.headless=true"); // For Mac builds
commandLine.add("-Djava.library.path=" + System.getProperty("java.library.path"));
commandLine.add(CentralPAPropertyRepository.PA_TEST.getCmdLine() + "true");
commandLine.add(SchedulerStartForFunctionalTest.class.getName());
commandLine.add(String.valueOf(configuration.hasLocalNodes()));
commandLine.add(configuration.getSchedulerConfigFile());
commandLine.add(configuration.getRMConfigFile());
String rmToConnectTo;
if (configuration.getRMToConnectTo() != null) {
rmToConnectTo = configuration.getRMToConnectTo();
commandLine.add(configuration.getRMToConnectTo());
} else {
rmToConnectTo = schedulerUrl;
}
rmUrl = rmToConnectTo;
System.out.println("Starting Scheduler process: " + commandLine);
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
processBuilder.redirectErrorStream(true);
processTreeKiller = CookieBasedProcessTreeKiller.createProcessChildrenKiller("TEST_SCHED",
processBuilder.environment());
schedulerProcess = processBuilder.start();
InputStreamReaderThread outputReader = new InputStreamReaderThread(schedulerProcess.getInputStream(),
"[Scheduler output]: ");
outputReader.start();
System.out.println("Waiting for the Scheduler using URL: " + schedulerUrl);
rmAuth = RMConnection.waitAndJoin(rmToConnectTo, 120000);
startLocalNodes(configuration);
schedulerAuth = SchedulerConnection.waitAndJoin(schedulerUrl, 120000);
System.out.println("The Scheduler is up and running");
isStarted = true;
}
public static boolean isStarted() {
return isStarted;
}
private static void startLocalNodes(SchedulerTestConfiguration configuration)
throws KeyException, LoginException, InterruptedException {
if (configuration.hasLocalNodes()) {
// Waiting while all the nodes will be registered in the RM.
// Without waiting test can finish earlier than nodes are added.
// It leads to test execution hang up on windows due to running processes.
Credentials creds = Credentials.createCredentials(new CredData(CredData.parseLogin(TestUsers.DEMO.username),
CredData.parseDomain(TestUsers.DEMO.username),
TestUsers.DEMO.password),
rmAuth.getPublicKey());
ResourceManager rm = rmAuth.login(creds);
while (rm.getState().getTotalAliveNodesNumber() < SchedulerStartForFunctionalTest.RM_NODE_NUMBER) {
Thread.sleep(50);
}
PAFuture.waitFor(rm.disconnect());
System.out.println("Nodes are deployed");
}
}
public static void kill() throws Exception {
if (schedulerProcess != null) {
schedulerProcess.destroy();
schedulerProcess.waitFor();
processTreeKiller.kill();
schedulerProcess = null;
isStarted = false;
}
}
public static String testClasspath() {
return (getRmHome() + File.separator + "dist" + File.separator + "lib" + File.separator + "*") +
File.pathSeparatorChar + getRmHome() + File.separator + "addons" + File.separator + "*" +
filterClassPath(System.getProperty("java.class.path"));
}
private static String getRmHome() {
return PAResourceManagerProperties.RM_HOME.getValueAsString();
}
private static String filterClassPath(String classPath) {
Set<String> distLibJars = findJarsNamesInPath(getRmHome() + File.separator + "dist" + File.separator + "lib");
Set<String> addonsJars = findJarsNamesInPath(getRmHome() + File.separator + "addons");
List<String> pathList = Arrays.asList(classPath.split("" + File.pathSeparatorChar));
StringBuilder builder = new StringBuilder();
for (String pathElement : pathList) {
if (pathElement.endsWith(".so") || pathElement.endsWith(".dll") || pathElement.endsWith(".lib") ||
pathElement.endsWith(".dylib")) {
continue;
} else if (distLibJars.contains(new File(pathElement).getName())) {
continue;
} else if (addonsJars.contains(new File(pathElement).getName())) {
continue;
} else {
builder.append(File.pathSeparatorChar);
builder.append(pathElement);
}
}
return builder.toString();
}
private static Set<String> findJarsNamesInPath(String path) {
File[] jarArray = new File(path).listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".jar");
}
});
HashSet<String> jarNames = new HashSet<>();
for (File jar : jarArray) {
jarNames.add(jar.getName());
}
return jarNames;
}
/* convenience method to clean TMP from dataspace when executing test */
private static void cleanTMP() {
File tmp = new File(System.getProperty("java.io.tmpdir"));
for (File f : tmp.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.startsWith("PA_JVM");
}
})) {
FileUtils.removeDir(f);
}
}
public static synchronized SchedulerAuthenticationInterface getAuth() {
return schedulerAuth;
}
public static boolean isStartedWithSameConfiguration(SchedulerTestConfiguration configuration)
throws URISyntaxException {
return schedulerProcess != null && startedConfiguration.equals(configuration);
}
public static synchronized RMAuthentication getRMAuth() {
return rmAuth;
}
public static String getUrl() {
return schedulerUrl;
}
public static String getRMUrl() {
return rmUrl;
}
}