AIRAVATA-2500 Add creation of scratch location
Project: http://git-wip-us.apache.org/repos/asf/airavata/repo Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/8c748c66 Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/8c748c66 Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/8c748c66 Branch: refs/heads/AIRAVATA-2500 Commit: 8c748c66b5f4c40847432b6abe5b1ca535188be9 Parents: 3d161b8 Author: Marcus Christie <[email protected]> Authored: Wed Aug 23 17:19:05 2017 -0400 Committer: Marcus Christie <[email protected]> Committed: Tue Sep 19 15:07:56 2017 -0400 ---------------------------------------------------------------------- .../accountprovisioning/SSHAccountManager.java | 11 ++- .../airavata/accountprovisioning/SSHUtil.java | 79 +++++++++++++++++++- 2 files changed, 84 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/airavata/blob/8c748c66/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java ---------------------------------------------------------------------- diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java index d565fe9..a56a632 100644 --- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java +++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java @@ -34,6 +34,8 @@ import org.apache.airavata.registry.api.RegistryService; import org.apache.airavata.registry.api.client.RegistryServiceClientFactory; import org.apache.airavata.registry.api.exception.RegistryServiceException; import org.apache.thrift.TException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.List; @@ -43,6 +45,8 @@ import java.util.stream.Collectors; public class SSHAccountManager { + private final static Logger logger = LoggerFactory.getLogger(SSHAccountManager.class); + // TODO: change return type to one that returns some details of the SSH account setup, for example the scratch location public static void setupSSHAccount(String gatewayId, String computeResourceId, String username, SSHCredential sshCredential) { @@ -84,8 +88,9 @@ public class SSHAccountManager { // Install SSH key sshAccountProvisioner.installSSHKey(username, sshCredential.getPublicKey()); + // TODO: replace hard coded port 22 with port from SSHJobSubmission interface // Verify can authenticate to host - boolean validated = SSHUtil.validate(username, computeResourceDescription.getHostName(), 22, sshCredential); + boolean validated = SSHUtil.validate(computeResourceDescription.getHostName(), 22, username, sshCredential); if (!validated) { throw new RuntimeException("Failed to validate installation of key for [" + username + "] on [" + computeResourceDescription.getHostName() + "] using SSH Account Provisioner [" @@ -93,8 +98,10 @@ public class SSHAccountManager { } // create the scratch location on the host - // TODO: create the scratch location String scratchLocation = sshAccountProvisioner.getScratchLocation(username); + SSHUtil.execute(computeResourceDescription.getHostName(), 22, username, sshCredential, "mkdir -p " + scratchLocation); + + // TODO: return information about provisioned account } private static Map<ConfigParam, String> resolveProvisionerConfig(String gatewayId, String provisionerName, Map<ConfigParam, String> provisionerConfig) { http://git-wip-us.apache.org/repos/asf/airavata/blob/8c748c66/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java ---------------------------------------------------------------------- diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java index 4b5452a..2550270 100644 --- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java +++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java @@ -20,12 +20,14 @@ package org.apache.airavata.accountprovisioning; -import com.jcraft.jsch.JSch; -import com.jcraft.jsch.JSchException; -import com.jcraft.jsch.Session; +import com.jcraft.jsch.*; import org.apache.airavata.model.credential.store.SSHCredential; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -36,7 +38,9 @@ import java.util.UUID; */ public class SSHUtil { - public static boolean validate(String username, String hostname, int port, SSHCredential sshCredential) { + private final static Logger logger = LoggerFactory.getLogger(SSHUtil.class); + + public static boolean validate(String hostname, int port, String username, SSHCredential sshCredential) { JSch jSch = new JSch(); Session session = null; @@ -57,6 +61,73 @@ public class SSHUtil { } } + public static String execute(String hostname, int port, String username, SSHCredential sshCredential, String command) { + JSch jSch = new JSch(); + Session session = null; + Channel channel = null; + try { + jSch.addIdentity(UUID.randomUUID().toString(), sshCredential.getPrivateKey().getBytes(), sshCredential.getPublicKey().getBytes(), sshCredential.getPassphrase().getBytes()); + session = jSch.getSession(username, hostname, port); + java.util.Properties config = new java.util.Properties(); + config.put("StrictHostKeyChecking", "no"); + session.setConfig(config); + session.connect(); + + channel = session.openChannel("exec"); + ((ChannelExec)channel).setCommand(command); + ByteArrayOutputStream errOutputStream = new ByteArrayOutputStream(); + ((ChannelExec) channel).setErrStream(errOutputStream); + channel.connect(); + + try (InputStream in = channel.getInputStream()) { + byte[] tmp = new byte[1024]; + String result = ""; + Integer exitStatus; + + while (true) { + while (in.available() > 0) { + int i = in.read(tmp, 0, 1024); + if (i < 0) break; + result += new String(tmp, 0, i); + } + if (channel.isClosed()) { + if (in.available() > 0) continue; + exitStatus = channel.getExitStatus(); + break; + } + try { + Thread.sleep(1000); + } catch (Exception e) { + } + } + + logger.debug("Output from command: " + result); + logger.debug("Exit status: " + exitStatus); + + if (exitStatus == null || exitStatus != 0) { + String stderr = errOutputStream.toString("UTF-8"); + if (stderr != null && stderr.length() > 0) { + logger.error("STDERR for command [" + command + "]: " + stderr); + } + throw new RuntimeException("SSH command [" + command + "] exited with exit status: " + exitStatus + ", STDERR=" + stderr); + } + + return result; + } + } catch (JSchException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if (channel != null && channel.isConnected()) { + channel.disconnect(); + } + if (session != null && session.isConnected()) { + session.disconnect(); + } + } + } + public static void main(String[] args) throws JSchException { // Test the validate method
