package org.ourgrid.common.executor.gateway; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.ourgrid.common.executor.AbstractExecutor; import org.ourgrid.common.executor.ExecutorException; import org.ourgrid.common.executor.ExecutorHandle; import org.ourgrid.common.executor.ExecutorResult; import org.ourgrid.common.executor.IntegerExecutorHandle; import org.ourgrid.common.executor.config.ExecutorConfiguration; import org.ourgrid.common.executor.config.GatewayExecutorConfiguration; import org.ourgrid.common.util.StringUtil; import org.ourgrid.gateway.wssubmitter.GatewayBridgeSubmitter; import org.ourgrid.gateway.wssubmitter.client.GatewayBridgeSubmitterClient; import org.ourgrid.gateway.wssubmitter.client.Job; import org.ourgrid.gateway.wssubmitter.client.JobIDList; import org.ourgrid.gateway.wssubmitter.client.JobList; import org.ourgrid.gateway.wssubmitter.client.JobOutput; import org.ourgrid.gateway.wssubmitter.client.JobStatus; import org.ourgrid.gateway.wssubmitter.client.LogicalFile; import org.ourgrid.gateway.wssubmitter.client.OutputList; import org.ourgrid.gateway.wssubmitter.client.StatusList; import org.ourgrid.worker.WorkerConfiguration; import org.ourgrid.worker.WorkerConstants; import br.edu.ufcg.lsd.commune.container.logging.CommuneLogger; public class GatewayExecutor extends AbstractExecutor { private static final int GET_RESULT_INTERVAL = 10000; private static final long serialVersionUID = 6385184394295862967L; private String destinationGrid; private String publicDirPath; private String publicDirURL; private String gatewayServiceAddress; private GatewayBridgeSubmitter bridgeSubmitter; private Map<ExecutorHandle, GatewayJob> jobsIds = new TreeMap<ExecutorHandle, GatewayJob>(); private int nextHandle = 0; public GatewayExecutor(CommuneLogger logger) { super(logger); } public void prepareAllocation() throws ExecutorException { } public void chmod(File file, String perm) throws ExecutorException { // TODO Auto-generated method stub } public ExecutorHandle execute(String dirName, String command, Map<String, String> envVars) throws ExecutorException { String inputVars = envVars.get(WorkerConfiguration.ATT_INPUTFILES); String[] inputFiles = inputVars == null ? new String[]{} : inputVars.split( WorkerConfiguration.SEPARATOR_CHAR); waitForInputsToBeStaged(envVars, inputFiles); JobList jobList = new JobList(); command = command.trim(); String[] splitCommand = command.split(" "); Job job = new Job(); job.setAlg(splitCommand[0]); if (splitCommand.length > 1) { job.setArgs(command.substring(splitCommand[0].length()).trim()); } getLogger().debug("Setting destination grid for execution: " + destinationGrid); job.setGrid(destinationGrid); String outputVars = envVars.get(WorkerConfiguration.ATT_OUTPUTFILES); String[] outputFiles = outputVars == null ? new String[]{} : outputVars.split( WorkerConfiguration.SEPARATOR_CHAR); Map<String, String> resolvedOutputs = new HashMap<String, String>(); for (String outputFile : outputFiles) { job.getOutputs().add(outputFile); resolvedOutputs.put(outputFile, resolveLogicalName(envVars, outputFile)); } for (String inputFile : inputFiles) { String resolvedFileName = resolveLogicalName(envVars, inputFile); if(WorkerConstants.CERTIFICATE_FILE_NAME.equals(inputFile)){ String proxy = getProxy(resolvedFileName); job.setUsercert(proxy); } else { LogicalFile logicalFile = new LogicalFile(); logicalFile.setURL(copyFileToPublicDir(inputFile, resolvedFileName, new File(envVars.get(WorkerConstants.ENV_PLAYPEN)).getName())); logicalFile.setLogicalName(inputFile); job.getInputs().add(logicalFile); } try { Thread.sleep(1000); } catch (InterruptedException e) { throw new ExecutorException(e); } } jobList.getJob().add(job); getLogger().debug("Invoking gateway webservice to submit job: " + job.getAlg()); JobIDList jobIDList = getBridgeSubmitter().submit(jobList); IntegerExecutorHandle handle = new IntegerExecutorHandle(nextHandle++); String jobID = jobIDList.getJobid().iterator().next(); getLogger().debug("Job submitted to gateway with id: " + jobID); GatewayJob gJob = new GatewayJob(jobID, job, resolvedOutputs); jobsIds.put(handle, gJob); return handle; } private void waitForInputsToBeStaged(Map<String, String> envVars, String[] inputFiles) throws ExecutorException { int tries = 120; try { Thread.sleep(GET_RESULT_INTERVAL); } catch (InterruptedException e) { throw new ExecutorException(e); } while (true) { boolean allFilesStaged = true; for (String inputFile : inputFiles) { String resolvedFileName = resolveLogicalName(envVars, inputFile); allFilesStaged &= new File(resolvedFileName).exists(); if (!allFilesStaged) { break; } } if (!allFilesStaged) { tries--; } else { return; } if (tries == 0) { throw new ExecutorException("Input files were not staged."); } try { Thread.sleep(1000); } catch (InterruptedException e) { throw new ExecutorException(e); } } } private String copyFileToPublicDir(String logicalFileName, String inputFile, String playpenDir) throws ExecutorException { try { FileUtils.copyFileToDirectory(new File(inputFile), new File(publicDirPath + File.separator + playpenDir)); } catch (IOException e) { throw new ExecutorException(e); } return publicDirURL + "/" + playpenDir + "/" + logicalFileName; } public String getProxy(String proxyPath) throws ExecutorException{ try { return IOUtils.toString(new FileInputStream(proxyPath)); } catch (IOException ioe) { getLogger().debug(ioe.getMessage()); throw new ExecutorException("Error while loading proxy file.", ioe); } } private String resolveLogicalName(Map<String, String> envVars, String inputFile) { String playpenDir = envVars.get(WorkerConstants.ENV_PLAYPEN); String storageDir = envVars.get(WorkerConstants.ENV_STORAGE); int indexOfPlaypenDir = inputFile.indexOf(playpenDir); int indexOfStorageDir = inputFile.indexOf(storageDir); if (indexOfPlaypenDir < 0 && indexOfStorageDir < 0) { return playpenDir + File.separator + inputFile; } return StringUtil.replaceVariables(inputFile, envVars); } public ExecutorHandle execute(String dirName, String command) throws ExecutorException { return execute(dirName, command, new HashMap<String, String>()); } public void finishExecution() throws ExecutorException { // TODO Auto-generated method stub } public ExecutorResult getResult(ExecutorHandle handle) throws ExecutorException { GatewayJob gJob = jobsIds.get(handle); JobIDList jobIdList = new JobIDList(); jobIdList.getJobid().add(gJob.getJobId()); while (true) { getLogger().debug("Getting status for job with id: " + gJob.getJobId()); StatusList statusList = getBridgeSubmitter().getStatus(jobIdList); JobStatus jobStatus = statusList.getStatus().iterator().next(); if (JobStatus.ERROR.equals(jobStatus)) { throw new ExecutorException("The job execution at the Grid Gateway failed."); } else if (JobStatus.FINISHED.equals(jobStatus)) { fetchOutputs(gJob); return new ExecutorResult(0, "", ""); } } } private void fetchOutputs(GatewayJob gJob) throws ExecutorException { JobIDList jobIdList = new JobIDList(); jobIdList.getJobid().add(gJob.getJobId()); OutputList outputList = getBridgeSubmitter().getOutput(jobIdList); for (JobOutput jobOutput : outputList.getOutput()) { List<LogicalFile> logicalFiles = jobOutput.getOutput(); if (logicalFiles.size() != gJob.getJob().getOutputs().size()) { throw new ExecutorException("Outputs fetched from the bridge differs " + "from the ones specified on the job description"); } for (LogicalFile logicalFile : logicalFiles) { wget(logicalFile, gJob.getOutputs().get(logicalFile.getLogicalName())); } } } private void wget(LogicalFile logicalFile, String fullFilePath) throws ExecutorException { try { URL url = new URL(logicalFile.getURL()); FileUtils.copyURLToFile(url, new File(fullFilePath)); } catch (Exception e) { throw new ExecutorException(e); } } public void kill(ExecutorHandle handle) throws ExecutorException { if(handle != null){ GatewayJob gJob = jobsIds.get(handle); if(gJob != null){ JobIDList jobIDList = new JobIDList(); jobIDList.getJobid().add(gJob.getJobId()); getBridgeSubmitter().delete(jobIDList); } } } public void setConfiguration(ExecutorConfiguration executorConfiguratrion) { this.destinationGrid = executorConfiguratrion.getProperty(WorkerConstants.PREFIX + GatewayExecutorConfiguration.PROPERTIES.DESTINATION_GRID.toString()); this.publicDirPath = executorConfiguratrion.getProperty(WorkerConstants.PREFIX + GatewayExecutorConfiguration.PROPERTIES.PUBLIC_DIR_PATH.toString()); this.publicDirURL = executorConfiguratrion.getProperty(WorkerConstants.PREFIX + GatewayExecutorConfiguration.PROPERTIES.PUBLIC_DIR_URL.toString()); this.gatewayServiceAddress = executorConfiguratrion.getProperty(WorkerConstants.PREFIX + GatewayExecutorConfiguration.PROPERTIES.WS_URL.toString()); } public GatewayBridgeSubmitter getBridgeSubmitter() throws ExecutorException { if (bridgeSubmitter == null) { try { bridgeSubmitter = new GatewayBridgeSubmitterClient(gatewayServiceAddress).getG3BridgeSubmitterPort(); } catch (Throwable e) { getLogger().error("Cannot access gateway webservice: " + e.getMessage()); throw new ExecutorException("Cannot access gateway webservice: " + e.getMessage()); } } return bridgeSubmitter; } public void finishCommandExecution(ExecutorHandle handle) throws ExecutorException { } public void killPreparingAllocation() throws ExecutorException { } @Override public void shutdown() throws ExecutorException { // TODO Auto-generated method stub } }