/** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.airavata.gfac.impl.task.utils; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import org.apache.airavata.common.exception.AiravataException; import org.apache.airavata.credential.store.store.CredentialStoreException; import org.apache.airavata.gfac.core.GFacException; import org.apache.airavata.gfac.core.GFacUtils; import org.apache.airavata.gfac.core.SSHApiException; import org.apache.airavata.gfac.core.authentication.AuthenticationInfo; import org.apache.airavata.gfac.core.cluster.CommandInfo; import org.apache.airavata.gfac.core.cluster.RawCommandInfo; import org.apache.airavata.gfac.core.cluster.RemoteCluster; import org.apache.airavata.gfac.core.cluster.ServerInfo; import org.apache.airavata.gfac.core.context.TaskContext; import org.apache.airavata.gfac.impl.Factory; import org.apache.airavata.gfac.impl.SSHUtils; import org.apache.airavata.model.status.JobState; import org.apache.airavata.model.status.JobStatus; import org.apache.airavata.model.task.DataStagingTaskModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.TimerTask; public class StreamData extends TimerTask { private static final Logger log = LoggerFactory.getLogger(StreamData.class); private static final int DEFAULT_SSH_PORT = 22; private String publicKeyPath; private String passPhrase; private String privateKeyPath; private String userName; private String hostName; private String inputPath; private TaskContext taskContext; private DataStagingTaskModel subTaskModel; public StreamData(String userName, String hostName, String inputPath, TaskContext taskContext, DataStagingTaskModel subTaskModel) { this.userName = userName; this.hostName = hostName; this.inputPath = inputPath; this.taskContext = taskContext; this.subTaskModel = subTaskModel; } @Override public void run() { try { // output staging should start when the job is in active state JobStatus jobStatus = taskContext.getParentProcessContext().getJobModel().getJobStatuses().get(0); if (jobStatus != null && jobStatus.getJobState().equals(JobState.ACTIVE)){ runOutputStaging(); } // output staging should end when the job is complete if (jobStatus != null && jobStatus.getJobState().equals(JobState.COMPLETE) || jobStatus.getJobState().equals(JobState.CANCELED) || jobStatus.getJobState().equals(JobState.FAILED)){ this.cancel(); } } catch (URISyntaxException e) { log.error("expId: {}, processId:{}, taskId: {}:- Couldn't stage file {} , Erroneous path specified", taskContext.getExperimentId(), taskContext.getProcessId(), taskContext.getTaskId(), taskContext.getProcessOutput().getName()); } catch (IllegalAccessException | InstantiationException | AiravataException | IOException | JSchException e) { log.error("expId: {}, processId:{}, taskId: {}:- Couldn't stage file {} , Error occurred while streaming data", taskContext.getExperimentId(), taskContext.getProcessId(), taskContext.getTaskId(), taskContext.getProcessOutput().getName()); } catch (CredentialStoreException e) { log.error("expId: {}, processId:{}, taskId: {}:- Couldn't stage file {} , Error occurred while connecting with credential store", taskContext.getExperimentId(), taskContext.getProcessId(), taskContext.getTaskId(), taskContext.getProcessOutput().getName()); } } public void runOutputStaging() throws URISyntaxException, IllegalAccessException, InstantiationException, CredentialStoreException, AiravataException, IOException, JSchException { try { AuthenticationInfo authenticationInfo = null; URI sourceURI = new URI(subTaskModel.getSource()); String fileName = sourceURI.getPath().substring(sourceURI.getPath().lastIndexOf(File.separator) + 1, sourceURI.getPath().length()); URI destinationURI = null; if (subTaskModel.getDestination().startsWith("dummy")) { destinationURI = getDestinationURI(taskContext, fileName); subTaskModel.setDestination(destinationURI.toString()); } else { destinationURI = new URI(subTaskModel.getDestination()); } if (sourceURI.getHost().equalsIgnoreCase(destinationURI.getHost()) && sourceURI.getUserInfo().equalsIgnoreCase(destinationURI.getUserInfo())) { localDataCopy(taskContext, sourceURI, destinationURI); } authenticationInfo = Factory.getStorageSSHKeyAuthentication(taskContext.getParentProcessContext()); ServerInfo serverInfo = taskContext.getParentProcessContext().getStorageResourceServerInfo(); Session sshSession = Factory.getSSHSession(authenticationInfo, serverInfo); String targetPath = destinationURI.getPath().substring(0, destinationURI.getPath().lastIndexOf('/')); SSHUtils.makeDirectory(targetPath, sshSession); outputDataStaging(taskContext, sshSession, sourceURI, destinationURI); } catch (GFacException e) { log.error("expId: {}, processId:{}, taskId: {}:- Couldn't stage file {} , Error while output staging", taskContext.getExperimentId(), taskContext.getProcessId(), taskContext.getTaskId(), taskContext.getProcessOutput().getName()); throw new AiravataException("Error while output staging",e); } } private void localDataCopy(TaskContext taskContext, URI sourceURI, URI destinationURI) throws GFacException { StringBuilder sb = new StringBuilder("rsync -cr "); sb.append(sourceURI.getPath()).append(" ").append(destinationURI.getPath()); CommandInfo commandInfo = new RawCommandInfo(sb.toString()); taskContext.getParentProcessContext().getDataMovementRemoteCluster().execute(commandInfo); } public URI getDestinationURI(TaskContext taskContext, String fileName) throws URISyntaxException { String filePath = (inputPath.endsWith(File.separator) ? inputPath : inputPath + File.separator) + taskContext.getParentProcessContext().getProcessId() + File.separator + fileName; return new URI("SCP", hostName, filePath, null); } private void outputDataStaging(TaskContext taskContext, Session sshSession, URI sourceURI, URI destinationURI) throws AiravataException, IOException, JSchException, GFacException { /** * scp third party file transfer 'from' comute resource. */ taskContext.getParentProcessContext().getDataMovementRemoteCluster().scpThirdParty(sourceURI.getPath(), destinationURI.getPath(), sshSession, RemoteCluster.DIRECTION.TO, true); // update output locations GFacUtils.saveExperimentOutput(taskContext.getParentProcessContext(), taskContext.getProcessOutput().getName(), destinationURI.getPath()); GFacUtils.saveProcessOutput(taskContext.getParentProcessContext(), taskContext.getProcessOutput().getName(), destinationURI.getPath()); } }