/* * RapidMiner * * Copyright (C) 2001-2011 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program 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, either version 3 of the License, or * (at your option) any later version. * * 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/. */ package com.rapidminer.repository.remote; import java.io.PrintStream; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; import com.rapid_i.repository.wsimport.ExecutionResponse; import com.rapid_i.repository.wsimport.ProcessResponse; import com.rapid_i.repository.wsimport.ProcessService; import com.rapid_i.repository.wsimport.ProcessStackTrace; import com.rapid_i.repository.wsimport.ProcessStackTraceElement; import com.rapid_i.repository.wsimport.RepositoryService; import com.rapidminer.repository.RemoteProcessState; import com.rapidminer.repository.RepositoryException; import com.rapidminer.repository.RepositoryManager; import com.rapidminer.tools.Tools; /** This class can be used to access a RapidAnalytics installation from a remote machine. * Currently, it can only be used to trigger the execution of jobs. * * @author Simon Fischer * */ public class RapidAnalyticsCLTool { private static final String NULL = new String(); private Map<String,String> argsMap = new HashMap<String,String>(); private long delay = 1000; private boolean dumpStatus = false; private boolean watch = false; private RapidAnalyticsCLTool(String[] args) { extractArguments(args); } private void extractArguments(String[] args) { for (int i = 0; i < args.length; i++) { if (args[i].startsWith("--")) { args[i] = args[i].substring(2); if (args[i].equals("help")) { printUsage(); System.exit(0); } String[] split = args[i].split("=", 2); switch (split.length) { case 1: argsMap.put(split[0], NULL); break; case 2: argsMap.put(split[0], split[1]); break; default: // cannot happen System.err.println("Arguments must be of the form \"--key=value\"."); System.exit(1); break; } } else { System.err.println("Arguments must be of the form \"--key=value\"."); System.exit(1); } } } private void printUsage() { System.out.println(RapidAnalyticsCLTool.class.getName()+" [OPTIONS]"); System.out.println(" --check-state"); System.out.println(" Check state and exit with code 0 if server is up, state 1 if server does not respond or causes an error."); System.out.println(" --url=URL "); System.out.println(" Base URL of the RapidAnalytics installation."); System.out.println(" --user=USER "); System.out.println(" User name to use for logging in."); System.out.println(" --password=PASSWORD"); System.out.println(" Password to use for logging in."); System.out.println(" --execute-process=/PATH/TO/PROCESS"); System.out.println(" Process location to execute."); System.out.println(" --watch={true|false}"); System.out.println(" Watch process until completed."); System.out.println(" --process-id=ID"); System.out.println(" Manually specify process ID (for --watch). Unnecessary for --execute process."); System.out.println(" --delay=MILLIS"); System.out.println(" Loop delay in milliseconds when --watch is enabled."); } private boolean isArgumentSet(String argName) { return argsMap.containsKey(argName); } private String getArgument(String argName, String defaultValue) { String value = argsMap.get(argName); if (value != null) { return value; } else { if (defaultValue != null) { System.err.println("No value specified for --"+argName+", using default ("+defaultValue+")."); } return defaultValue; } } private int getArgumentInt(String argName, int defaultValue) { String value = argsMap.get(argName); if (value != null) { try { return Integer.parseInt(value); } catch (NumberFormatException e) { throw new IllegalArgumentException("Parameter "+argName+" must be a number."); } } else { return defaultValue; } } public void run() throws IllegalArgumentException, MalformedURLException, RepositoryException { String url = getArgument("url", "http://localhost:8080"); String user = getArgument("user", "admin"); String password = getArgument("password", "changeit"); System.err.println("Using RapidAnalytics server at "+url+"..."); RemoteRepository repository = new RemoteRepository(new URL(url), "Temp", user, password.toCharArray(), true); RepositoryManager.getInstance(null).addRepository(repository); if (isArgumentSet("check-state")) { long startTime; try { final RepositoryService repoService = repository.getRepositoryService(); startTime = System.currentTimeMillis(); repoService.getFolderContents("/"); } catch (Exception e) { System.err.println("Error checking state of RapidAnalytics server at "+url+": "+e); System.exit(1); return; } long responseTime = System.currentTimeMillis() - startTime; System.err.println("RapidAnalytics server at "+url+" is up. Response time was "+responseTime+" ms."); System.exit(0); return; } delay = getArgumentInt("delay", 1000); if ("true".equals(getArgument("watch", "false"))) { watch = true; dumpStatus = true; } int processId = -1; String executeProcess = getArgument("execute-process", null); if (executeProcess != null) { System.err.println("Scheduling process execution for process "+executeProcess); ExecutionResponse result = repository.getProcessService().executeProcessSimple(executeProcess, null, null); if (result.getStatus() != 0) { System.err.println("ERROR. Server responded with code "+result.getStatus()+": "+result.getErrorMessage()); System.exit(result.getStatus()); } else { System.out.println("Process scheduled for "+result.getFirstExecution()); int jobId = result.getJobId(); if (dumpStatus) { processId = getJobId(jobId, repository.getProcessService()); } else { processId = -1; } } } else { processId = getArgumentInt("process-id", -1); if (processId != -1) { dumpStatus = true; } } if (dumpStatus) { if (processId == -1) { throw new IllegalArgumentException("You must use --process-id or --execute-service if --watch=true."); } RemoteProcessState state; do { ProcessResponse pInfo = repository.getProcessService().getRunningProcessesInfo(processId); if (pInfo == null) { throw new IllegalArgumentException("Process with id "+processId + " does not exist."); } dump(pInfo, System.out); if (watch) { try { Thread.sleep(delay); } catch (InterruptedException e) { } } state = RemoteProcessState.valueOf(pInfo.getState()); } while (watch && !state.isTerminated()); if (!state.isSuccessful()) { System.exit(1); } else { System.exit(0); } } } private int getJobId(int jobId, ProcessService processService) { while (true) { System.err.println("Waiting for server to assign process id to scheduled job id "+jobId+"..."); List<Integer> result = processService.getProcessIdsForJobId(jobId); if ((result == null) || result.isEmpty()) { try { Thread.sleep(delay); } catch (InterruptedException e) { } } else { if (result.size() == 1) { final Integer id = result.get(0); System.err.println("Process id is "+id+"."); return id; } else { throw new RuntimeException("Server delivered non-unique process id: "+result); } } } } private void dump(ProcessResponse pInfo, PrintStream out) { out.println("State of process " + pInfo.getProcessLocation()+ " (id="+pInfo.getId()+")"); out.println(" Started: "+pInfo.getStartTime()); if (pInfo.getCompletionTime() != null) { out.println(" Completed: "+pInfo.getCompletionTime()); } out.println(" State: "+pInfo.getState()); if (pInfo.getException() != null) { out.println(" Exception: "+pInfo.getException()); } final ProcessStackTrace trace = pInfo.getTrace(); if (trace != null) { out.println(" Trace:"); for (ProcessStackTraceElement ste : trace.getElements()) { System.out.println(" "+ste.getOperatorName()+" ("+ste.getApplyCount()+", "+Tools.formatDuration(ste.getExecutionTime())+")"); } } } public static void main(String[] args) { try { new RapidAnalyticsCLTool(args).run(); } catch (IllegalArgumentException e) { System.err.println(e.getMessage()); System.exit(1); } catch (MalformedURLException e) { System.err.println(e.getMessage()); System.exit(1); } catch (RepositoryException e) { System.err.println(e.getMessage()); System.exit(1); } } }