mirror of https://github.com/apache/jclouds.git
new demo javaoverssh
git-svn-id: http://jclouds.googlecode.com/svn/trunk@2566 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
edc6ccc503
commit
26b2e20640
|
@ -157,10 +157,10 @@ public class MainApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
static RunningInstance runInstance(EC2Client client, String securityGroupName, String keyPairName) {
|
static RunningInstance runInstance(EC2Client client, String securityGroupName, String keyPairName) {
|
||||||
|
|
||||||
String script = new ScriptBuilder() // lamp install script
|
String script = new ScriptBuilder() // lamp install script
|
||||||
.addStatement(exec("runurl run.alestic.com/apt/upgrade"))//
|
.addStatement(exec("runurl run.alestic.com/apt/upgrade"))//
|
||||||
.addStatement(exec("runurl run.alestic.com/install/lamp"))//
|
.addStatement(exec("runurl run.alestic.com/install/lamp"))//
|
||||||
|
.addStatement(exec("apt-get -y install openjdk-6-jdk"))// no license agreement!
|
||||||
.build(OsFamily.UNIX);
|
.build(OsFamily.UNIX);
|
||||||
|
|
||||||
System.out.printf("%d: running instance%n", System.currentTimeMillis());
|
System.out.printf("%d: running instance%n", System.currentTimeMillis());
|
||||||
|
@ -183,8 +183,6 @@ public class MainApp {
|
||||||
// create utilities that wait for the instance to finish
|
// create utilities that wait for the instance to finish
|
||||||
RetryablePredicate<RunningInstance> runningTester = new RetryablePredicate<RunningInstance>(
|
RetryablePredicate<RunningInstance> runningTester = new RetryablePredicate<RunningInstance>(
|
||||||
new InstanceStateRunning(client.getInstanceServices()), 180, 5, TimeUnit.SECONDS);
|
new InstanceStateRunning(client.getInstanceServices()), 180, 5, TimeUnit.SECONDS);
|
||||||
RetryablePredicate<InetSocketAddress> socketTester = new RetryablePredicate<InetSocketAddress>(
|
|
||||||
new SocketOpen(), 180, 1, TimeUnit.SECONDS);
|
|
||||||
|
|
||||||
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance
|
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance
|
||||||
.getId());
|
.getId());
|
||||||
|
@ -193,6 +191,8 @@ public class MainApp {
|
||||||
|
|
||||||
instance = findInstanceById(client, instance.getId());
|
instance = findInstanceById(client, instance.getId());
|
||||||
|
|
||||||
|
RetryablePredicate<InetSocketAddress> socketTester = new RetryablePredicate<InetSocketAddress>(
|
||||||
|
new SocketOpen(), 300, 1, TimeUnit.SECONDS);
|
||||||
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(),
|
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(),
|
||||||
instance.getIpAddress());
|
instance.getIpAddress());
|
||||||
if (!socketTester.apply(new InetSocketAddress(instance.getIpAddress(), 22)))
|
if (!socketTester.apply(new InetSocketAddress(instance.getIpAddress(), 22)))
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (C) 2009 Cloud Conscious, LLC.
|
||||||
|
<info@cloudconscious.com>
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Licensed 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.
|
||||||
|
====================================================================
|
||||||
|
-->
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-tools-project</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>jclouds-antcontrib</artifactId>
|
||||||
|
<name>Ant test</name>
|
||||||
|
<properties>
|
||||||
|
<jclouds.test.listener></jclouds.test.listener>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.shrinkwrap</groupId>
|
||||||
|
<artifactId>shrinkwrap-impl-base</artifactId>
|
||||||
|
<version>1.0.0-alpha-3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-scriptbuilder</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.ant</groupId>
|
||||||
|
<artifactId>ant</artifactId>
|
||||||
|
<version>1.7.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.ant</groupId>
|
||||||
|
<artifactId>ant-jsch</artifactId>
|
||||||
|
<version>1.7.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jcraft</groupId>
|
||||||
|
<artifactId>jsch</artifactId>
|
||||||
|
<version>0.1.42</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<descriptorRefs>
|
||||||
|
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||||
|
</descriptorRefs>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,25 @@
|
||||||
|
====
|
||||||
|
|
||||||
|
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Licensed 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.
|
||||||
|
====================================================================
|
||||||
|
====
|
||||||
|
this is a simple ant script that executes a java command on a remote machine via ssh
|
||||||
|
1. find or download a copy of jclouds-antcontrib-1.0-SNAPSHOT-jar-with-dependencies.jar
|
||||||
|
- ex. ~/.m2/repository/org/jclouds/jclouds-antcontrib/1.0-SNAPSHOT/jclouds-antcontrib-1.0-SNAPSHOT-jar-with-dependencies.jar
|
||||||
|
- ex. curl http://jclouds.rimuhosting.com/maven2/snapshots/org/jclouds/jclouds-antcontrib/1.0-SNAPSHOT/jclouds-antcontrib-1.0-20091215.023231-1-jar-with-dependencies.jar >jclouds-antcontrib-all.jar
|
||||||
|
2. invoke ant, adding the library above, and passing the properties 'host' 'username' 'keyfile' which corresponds to your remote credentials
|
||||||
|
- ex. ant -lib ~/.m2/repository/org/jclouds/jclouds-antcontrib/1.0-SNAPSHOT/jclouds-antcontrib-1.0-SNAPSHOT-jar-with-dependencies.jar -Dhost=67.202.42.237 -Dusername=root -Dkeyfile=$HOME/.ssh/id_dsa
|
||||||
|
- ex. ant -lib jclouds-antcontrib-all.jar -Dhost=67.202.42.237 -Dusername=root -Dkeyfile=$HOME/.ssh/id_dsa
|
|
@ -0,0 +1,83 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Licensed 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.
|
||||||
|
====================================================================
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project name="javassh" default="javassh" basedir=".">
|
||||||
|
<description>
|
||||||
|
simple example build file
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<!-- set global properties for this build -->
|
||||||
|
<property name="src" location="src"/>
|
||||||
|
<property name="build" location="build"/>
|
||||||
|
<property name="dist" location="dist"/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
message="Please enter the ip or hostname of the ssh machine"
|
||||||
|
addproperty="host"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
message="Please enter the user you will connect as"
|
||||||
|
addproperty="username"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
message="Please enter the path to the dsa key"
|
||||||
|
addproperty="keyfile"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
message="Please enter the strings you'd like to test"
|
||||||
|
addproperty="line"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<target name="init">
|
||||||
|
<!-- Create the time stamp -->
|
||||||
|
<tstamp/>
|
||||||
|
<!-- Create the build directory structure used by compile -->
|
||||||
|
<mkdir dir="${build}"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="compile" depends="init" description="compile the source ">
|
||||||
|
<!-- Compile the java code from ${src} into ${build} -->
|
||||||
|
<javac srcdir="${src}" destdir="${build}"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="clean" description="clean up">
|
||||||
|
<!-- Delete the ${build} and ${dist} directory trees -->
|
||||||
|
<delete dir="${build}"/>
|
||||||
|
<delete dir="${dist}"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<taskdef name="javassh" classname="org.jclouds.tools.ant.JavaOverSsh"/>
|
||||||
|
|
||||||
|
<target name="javassh" depends="compile" description="remote execute the java command">
|
||||||
|
<echo message="normal java task"/>
|
||||||
|
<java classname="TestClass" classpath="${build}" dir="${user.dir}" >
|
||||||
|
<arg line="${line}"/>
|
||||||
|
</java>
|
||||||
|
<echo message="java task over ssh"/>
|
||||||
|
<javassh classname="TestClass" classpath="${build}" dir="${user.dir}" host="${host}" username="${username}" keyfile="${keyfile}" trust="true" remotedir="/tmp/test" >
|
||||||
|
<arg line="${line}"/>
|
||||||
|
</javassh>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,16 @@
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class TestClass {
|
||||||
|
public static void main(String... args) {
|
||||||
|
File cwd = new File(System.getProperty("user.dir"));
|
||||||
|
System.out.println("children:");
|
||||||
|
for (File child : cwd.listFiles())
|
||||||
|
System.out.println(" " + child);
|
||||||
|
System.out.println("what you wrote:");
|
||||||
|
System.out.println(Arrays.asList(args));
|
||||||
|
System.err.println("this is the error stream");
|
||||||
|
System.out.println("will exit 3:");
|
||||||
|
System.exit(3);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,560 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed 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.jclouds.tools.ant;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.BuildException;
|
||||||
|
import org.apache.tools.ant.Project;
|
||||||
|
import org.apache.tools.ant.Task;
|
||||||
|
import org.apache.tools.ant.taskdefs.Java;
|
||||||
|
import org.apache.tools.ant.taskdefs.optional.ssh.SSHUserInfo;
|
||||||
|
import org.apache.tools.ant.types.CommandlineJava;
|
||||||
|
import org.apache.tools.ant.types.Environment;
|
||||||
|
import org.apache.tools.ant.util.KeepAliveOutputStream;
|
||||||
|
import org.apache.tools.ant.util.TeeOutputStream;
|
||||||
|
import org.jboss.shrinkwrap.api.Archives;
|
||||||
|
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
|
||||||
|
import org.jboss.shrinkwrap.api.importer.ExplodedImporter;
|
||||||
|
import org.jboss.shrinkwrap.api.importer.ZipImporter;
|
||||||
|
import org.jboss.shrinkwrap.api.spec.JavaArchive;
|
||||||
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
import org.jclouds.scriptbuilder.domain.StatementList;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.io.Closeables;
|
||||||
|
import com.jcraft.jsch.ChannelExec;
|
||||||
|
import com.jcraft.jsch.ChannelSftp;
|
||||||
|
import com.jcraft.jsch.JSch;
|
||||||
|
import com.jcraft.jsch.JSchException;
|
||||||
|
import com.jcraft.jsch.Session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ported from Jsch SSHExec task.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class JavaOverSsh extends Java {
|
||||||
|
/** Default listen port for SSH daemon */
|
||||||
|
private static final int SSH_PORT = 22;
|
||||||
|
private String jvm = "/usr/bin/java";
|
||||||
|
private File localDirectory;
|
||||||
|
private File remoteDirectory;
|
||||||
|
private Environment env = new Environment();
|
||||||
|
private String host;
|
||||||
|
private String knownHosts;
|
||||||
|
private int port = SSH_PORT;
|
||||||
|
private SSHUserInfo userInfo = new SSHUserInfo();
|
||||||
|
private OsFamily osFamily = OsFamily.UNIX;
|
||||||
|
|
||||||
|
/** units are milliseconds, default is 0=infinite */
|
||||||
|
private long maxwait = 0;
|
||||||
|
|
||||||
|
/** for waiting for the command to finish */
|
||||||
|
private Thread watchDog = null;
|
||||||
|
private File outputFile;
|
||||||
|
private String outputProperty;
|
||||||
|
private String resultProperty;
|
||||||
|
private File errorFile;
|
||||||
|
private String errorProperty;
|
||||||
|
private boolean append;
|
||||||
|
|
||||||
|
private static final String TIMEOUT_MESSAGE = "Timeout period exceeded, connection dropped.";
|
||||||
|
|
||||||
|
public JavaOverSsh() {
|
||||||
|
super();
|
||||||
|
setFork(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaOverSsh(Task owner) {
|
||||||
|
super(owner);
|
||||||
|
setFork(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int executeJava() throws BuildException {
|
||||||
|
String command = convertJavaToScript(getCommandLine());
|
||||||
|
|
||||||
|
InputStream classpathJar = (getCommandLine().getClasspath() != null) ? makeClasspathJarOrNull(getCommandLine()
|
||||||
|
.getClasspath().list())
|
||||||
|
: null;
|
||||||
|
|
||||||
|
InputStream bootClasspathJar = (getCommandLine().getBootclasspath() != null) ? makeClasspathJarOrNull(getCommandLine()
|
||||||
|
.getBootclasspath().list())
|
||||||
|
: null;
|
||||||
|
|
||||||
|
InputStream currentDirectoryZip = Archives.create("cwd.zip", ZipExporter.class).as(
|
||||||
|
ExplodedImporter.class).importDirectory(localDirectory).as(ZipExporter.class)
|
||||||
|
.exportZip();
|
||||||
|
|
||||||
|
if (getHost() == null) {
|
||||||
|
throw new BuildException("Host is required.");
|
||||||
|
}
|
||||||
|
if (getUserInfo().getName() == null) {
|
||||||
|
throw new BuildException("Username is required.");
|
||||||
|
}
|
||||||
|
if (getUserInfo().getKeyfile() == null && getUserInfo().getPassword() == null) {
|
||||||
|
throw new BuildException("Password or Keyfile is required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
// execute the command
|
||||||
|
session = openSession();
|
||||||
|
session.setTimeout((int) maxwait);
|
||||||
|
ChannelSftp sftp = null;
|
||||||
|
sftp = (ChannelSftp) session.openChannel("sftp");
|
||||||
|
sftp.connect();
|
||||||
|
sftp.put(currentDirectoryZip, remoteDirectory + "/cwd.zip");
|
||||||
|
Closeables.closeQuietly(currentDirectoryZip);
|
||||||
|
|
||||||
|
if (classpathJar != null || bootClasspathJar != null) {
|
||||||
|
if (classpathJar != null) {
|
||||||
|
sftp.put(classpathJar, remoteDirectory + "/classpath.jar");
|
||||||
|
Closeables.closeQuietly(classpathJar);
|
||||||
|
}
|
||||||
|
if (bootClasspathJar != null) {
|
||||||
|
sftp.put(classpathJar, remoteDirectory + "/boot-classpath.jar");
|
||||||
|
Closeables.closeQuietly(classpathJar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final ChannelExec channel = (ChannelExec) session.openChannel("exec");
|
||||||
|
channel.setCommand(command);
|
||||||
|
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
TeeOutputStream teeOut = new TeeOutputStream(out, new KeepAliveOutputStream(System.out));
|
||||||
|
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
||||||
|
TeeOutputStream teeErr = new TeeOutputStream(err, new KeepAliveOutputStream(System.err));
|
||||||
|
|
||||||
|
channel.setOutputStream(teeOut);
|
||||||
|
channel.setExtOutputStream(teeOut);
|
||||||
|
channel.setErrStream(teeErr);
|
||||||
|
|
||||||
|
channel.connect();
|
||||||
|
|
||||||
|
// wait for it to finish
|
||||||
|
watchDog = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
while (!channel.isEOF()) {
|
||||||
|
if (watchDog == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
sleep(500);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watchDog.start();
|
||||||
|
watchDog.join(maxwait);
|
||||||
|
|
||||||
|
if (watchDog.isAlive()) {
|
||||||
|
// ran out of time
|
||||||
|
|
||||||
|
throw new BuildException(TIMEOUT_MESSAGE);
|
||||||
|
} else {
|
||||||
|
// completed successfully
|
||||||
|
return writeOutputAndReturnExitStatus(channel, out, err);
|
||||||
|
}
|
||||||
|
} catch (BuildException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (JSchException e) {
|
||||||
|
if (e.getMessage().indexOf("session is down") >= 0) {
|
||||||
|
throw new BuildException(TIMEOUT_MESSAGE, e);
|
||||||
|
} else {
|
||||||
|
throw new BuildException(e);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BuildException(e);
|
||||||
|
} finally {
|
||||||
|
if (session != null && session.isConnected()) {
|
||||||
|
session.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream makeClasspathJarOrNull(String... paths) {
|
||||||
|
if (paths != null && paths.length > 0) {
|
||||||
|
JavaArchive classpathArchive = Archives.create("classpath.jar", JavaArchive.class);
|
||||||
|
for (String path : paths) {
|
||||||
|
File file = new File(path);
|
||||||
|
if (file.exists()) {
|
||||||
|
if (file.isFile()) {
|
||||||
|
try {
|
||||||
|
classpathArchive.as(ZipImporter.class).importZip(
|
||||||
|
new ZipFile(file.getAbsolutePath()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new BuildException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
classpathArchive.as(ExplodedImporter.class).importDirectory(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return classpathArchive.as(ZipExporter.class).exportZip();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int writeOutputAndReturnExitStatus(final ChannelExec channel, ByteArrayOutputStream out,
|
||||||
|
ByteArrayOutputStream err) throws IOException {
|
||||||
|
if (outputProperty != null) {
|
||||||
|
getProject().setProperty(outputProperty, out.toString());
|
||||||
|
}
|
||||||
|
if (outputFile != null) {
|
||||||
|
writeToFile(err.toString(), append, outputFile);
|
||||||
|
}
|
||||||
|
if (errorProperty != null) {
|
||||||
|
getProject().setProperty(errorProperty, err.toString());
|
||||||
|
}
|
||||||
|
if (errorFile != null) {
|
||||||
|
writeToFile(out.toString(), append, errorFile);
|
||||||
|
}
|
||||||
|
if (resultProperty != null) {
|
||||||
|
getProject().setProperty(resultProperty, channel.getExitStatus() + "");
|
||||||
|
}
|
||||||
|
return channel.getExitStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a string to a file. If destination file exists, it may be overwritten depending on the
|
||||||
|
* "append" value.
|
||||||
|
*
|
||||||
|
* @param from
|
||||||
|
* string to write
|
||||||
|
* @param to
|
||||||
|
* file to write to
|
||||||
|
* @param append
|
||||||
|
* if true, append to existing file, else overwrite
|
||||||
|
* @exception Exception
|
||||||
|
* most likely an IOException
|
||||||
|
*/
|
||||||
|
private void writeToFile(String from, boolean append, File to) throws IOException {
|
||||||
|
FileWriter out = null;
|
||||||
|
try {
|
||||||
|
out = new FileWriter(to.getAbsolutePath(), append);
|
||||||
|
StringReader in = new StringReader(from);
|
||||||
|
char[] buffer = new char[8192];
|
||||||
|
int bytesRead;
|
||||||
|
while (true) {
|
||||||
|
bytesRead = in.read(buffer);
|
||||||
|
if (bytesRead == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
} finally {
|
||||||
|
if (out != null) {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String convertJavaToScript(CommandlineJava commandLine) {
|
||||||
|
checkNotNull(jvm, "jvm must be set");
|
||||||
|
checkNotNull(localDirectory, "dir must be set");
|
||||||
|
checkNotNull(remoteDirectory, "remotedir must be set");
|
||||||
|
List<Statement> statements = Lists.newArrayList();
|
||||||
|
String[] environment = env.getVariables();
|
||||||
|
if (environment != null) {
|
||||||
|
for (int i = 0; i < environment.length; i++) {
|
||||||
|
log("Setting environment variable: " + environment[i], Project.MSG_VERBOSE);
|
||||||
|
statements.add(exec("{export} " + environment[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statements.add(exec("{cd} " + remoteDirectory));
|
||||||
|
statements.add(exec("jar -xf cwd.zip"));
|
||||||
|
|
||||||
|
StringBuilder commandBuilder = new StringBuilder(jvm);
|
||||||
|
if (commandLine.getBootclasspath() != null
|
||||||
|
&& commandLine.getBootclasspath().list().length > 0) {
|
||||||
|
commandBuilder.append(" -Xbootclasspath:boot-classpath.jar");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandLine.getVmCommand().getArguments() != null
|
||||||
|
&& commandLine.getVmCommand().getArguments().length > 0) {
|
||||||
|
commandBuilder.append(" ");
|
||||||
|
String[] variables = commandLine.getVmCommand().getArguments();
|
||||||
|
for (int i = 0; i < variables.length; i++) {
|
||||||
|
commandBuilder.append(variables[i]);
|
||||||
|
if (i + 1 < variables.length)
|
||||||
|
commandBuilder.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (commandLine.getClasspath() != null && commandLine.getClasspath().list().length > 0) {
|
||||||
|
commandBuilder.append(" -cp classpath.jar");
|
||||||
|
}
|
||||||
|
if (commandLine.getSystemProperties() != null
|
||||||
|
&& commandLine.getSystemProperties().getVariables() != null
|
||||||
|
&& commandLine.getSystemProperties().getVariables().length > 0) {
|
||||||
|
commandBuilder.append(" ");
|
||||||
|
String[] variables = commandLine.getSystemProperties().getVariables();
|
||||||
|
for (int i = 0; i < variables.length; i++) {
|
||||||
|
commandBuilder.append(variables[i]);
|
||||||
|
if (i + 1 < variables.length)
|
||||||
|
commandBuilder.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commandBuilder.append(" ").append(commandLine.getClassname());
|
||||||
|
|
||||||
|
if (commandLine.getJavaCommand().getArguments() != null
|
||||||
|
&& commandLine.getJavaCommand().getArguments().length > 0) {
|
||||||
|
commandBuilder.append(" ");
|
||||||
|
String[] variables = commandLine.getJavaCommand().getArguments();
|
||||||
|
for (int i = 0; i < variables.length; i++) {
|
||||||
|
commandBuilder.append(variables[i]);
|
||||||
|
if (i + 1 < variables.length)
|
||||||
|
commandBuilder.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statements.add(exec(commandBuilder.toString()));
|
||||||
|
|
||||||
|
String command = new StatementList(statements).render(osFamily);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addEnv(Environment.Variable var) {
|
||||||
|
env.addVariable(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDir(File localDir) {
|
||||||
|
this.localDirectory = checkNotNull(localDir, "dir");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemotedir(File remotedir) {
|
||||||
|
this.remoteDirectory = checkNotNull(remotedir, "remotedir");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFork(boolean fork) {
|
||||||
|
if (!fork)
|
||||||
|
throw new IllegalArgumentException("this only operates when fork is set");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setJvm(String jvm) {
|
||||||
|
this.jvm = checkNotNull(jvm, "jvm");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remote host, either DNS name or IP.
|
||||||
|
*
|
||||||
|
* @param host
|
||||||
|
* The new host value
|
||||||
|
*/
|
||||||
|
public void setHost(String host) {
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the host.
|
||||||
|
*
|
||||||
|
* @return the host
|
||||||
|
*/
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Username known to remote host.
|
||||||
|
*
|
||||||
|
* @param username
|
||||||
|
* The new username value
|
||||||
|
*/
|
||||||
|
public void setUsername(String username) {
|
||||||
|
userInfo.setName(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the password for the user.
|
||||||
|
*
|
||||||
|
* @param password
|
||||||
|
* The new password value
|
||||||
|
*/
|
||||||
|
public void setPassword(String password) {
|
||||||
|
userInfo.setPassword(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the keyfile for the user.
|
||||||
|
*
|
||||||
|
* @param keyfile
|
||||||
|
* The new keyfile value
|
||||||
|
*/
|
||||||
|
public void setKeyfile(String keyfile) {
|
||||||
|
userInfo.setKeyfile(keyfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the passphrase for the users key.
|
||||||
|
*
|
||||||
|
* @param passphrase
|
||||||
|
* The new passphrase value
|
||||||
|
*/
|
||||||
|
public void setPassphrase(String passphrase) {
|
||||||
|
userInfo.setPassphrase(passphrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the path to the file that has the identities of all known hosts. This is used by SSH
|
||||||
|
* protocol to validate the identity of the host. The default is
|
||||||
|
* <i>${user.home}/.ssh/known_hosts</i>.
|
||||||
|
*
|
||||||
|
* @param knownHosts
|
||||||
|
* a path to the known hosts file.
|
||||||
|
*/
|
||||||
|
public void setKnownhosts(String knownHosts) {
|
||||||
|
this.knownHosts = knownHosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setting this to true trusts hosts whose identity is unknown.
|
||||||
|
*
|
||||||
|
* @param yesOrNo
|
||||||
|
* if true trust the identity of unknown hosts.
|
||||||
|
*/
|
||||||
|
public void setTrust(boolean yesOrNo) {
|
||||||
|
userInfo.setTrust(yesOrNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the port used to connect to the remote host.
|
||||||
|
*
|
||||||
|
* @param port
|
||||||
|
* port number of remote host.
|
||||||
|
*/
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the port attribute.
|
||||||
|
*
|
||||||
|
* @return the port
|
||||||
|
*/
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the task. This initializizs the known hosts and sets the default port.
|
||||||
|
*
|
||||||
|
* @throws BuildException
|
||||||
|
* on error
|
||||||
|
*/
|
||||||
|
public void init() throws BuildException {
|
||||||
|
super.init();
|
||||||
|
this.knownHosts = System.getProperty("user.home") + "/.ssh/known_hosts";
|
||||||
|
this.port = SSH_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open an ssh seession.
|
||||||
|
*
|
||||||
|
* @return the opened session
|
||||||
|
* @throws JSchException
|
||||||
|
* on error
|
||||||
|
*/
|
||||||
|
protected Session openSession() throws JSchException {
|
||||||
|
JSch jsch = new JSch();
|
||||||
|
if (null != userInfo.getKeyfile()) {
|
||||||
|
jsch.addIdentity(userInfo.getKeyfile());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userInfo.getTrust() && knownHosts != null) {
|
||||||
|
log("Using known hosts: " + knownHosts, Project.MSG_DEBUG);
|
||||||
|
jsch.setKnownHosts(knownHosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session session = jsch.getSession(userInfo.getName(), host, port);
|
||||||
|
session.setUserInfo(userInfo);
|
||||||
|
log("Connecting to " + host + ":" + port);
|
||||||
|
session.connect();
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the user information.
|
||||||
|
*
|
||||||
|
* @return the user information
|
||||||
|
*/
|
||||||
|
protected SSHUserInfo getUserInfo() {
|
||||||
|
return userInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection can be dropped after a specified number of milliseconds. This is sometimes
|
||||||
|
* useful when a connection may be flaky. Default is 0, which means "wait forever".
|
||||||
|
*
|
||||||
|
* @param timeout
|
||||||
|
* The new timeout value in seconds
|
||||||
|
*/
|
||||||
|
public void setTimeout(long timeout) {
|
||||||
|
maxwait = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setError(File out) {
|
||||||
|
this.errorFile = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setErrorProperty(String errorProp) {
|
||||||
|
this.errorProperty = errorProp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOutput(File out) {
|
||||||
|
this.outputFile = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOutputproperty(String outputProp) {
|
||||||
|
this.outputProperty = outputProp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setResultProperty(String resultProperty) {
|
||||||
|
this.resultProperty = resultProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAppend(boolean append) {
|
||||||
|
this.append = append;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed 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.jclouds.tools.ant;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.Project;
|
||||||
|
import org.apache.tools.ant.types.Environment;
|
||||||
|
import org.apache.tools.ant.types.Path;
|
||||||
|
import org.apache.tools.ant.types.Environment.Variable;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "jclouds.JavaOverSshTest")
|
||||||
|
public class JavaOverSshTest {
|
||||||
|
|
||||||
|
public void testFull() throws SecurityException, NoSuchMethodException {
|
||||||
|
JavaOverSsh task = createTask();
|
||||||
|
assertEquals(
|
||||||
|
String
|
||||||
|
.format(
|
||||||
|
"cd /tmp/foo\njar -xf cwd.zip\n%s -Xms256 -cp classpath.jar -Dfooble=baz -Dfoo=bar org.jclouds.tools.ant.TestClass hello world\n",
|
||||||
|
System.getProperty("java.home") + "/bin/java", System
|
||||||
|
.getProperty("user.dir")), task.convertJavaToScript(task
|
||||||
|
.getCommandLine()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaOverSsh createTask() {
|
||||||
|
Project p = new Project();
|
||||||
|
JavaOverSsh task = new JavaOverSsh();
|
||||||
|
task.setProject(p);
|
||||||
|
task.setClassname(TestClass.class.getName());
|
||||||
|
task.createClasspath().add(new Path(p, "target/test-classes"));
|
||||||
|
Variable prop1 = new Environment.Variable();
|
||||||
|
prop1.setKey("fooble");
|
||||||
|
prop1.setValue("baz");
|
||||||
|
|
||||||
|
task.addSysproperty(prop1);
|
||||||
|
Variable prop2 = new Environment.Variable();
|
||||||
|
prop2.setKey("foo");
|
||||||
|
prop2.setValue("bar");
|
||||||
|
|
||||||
|
task.addSysproperty(prop2);
|
||||||
|
task.createJvmarg().setValue("-Xms256");
|
||||||
|
task.createArg().setValue("hello");
|
||||||
|
task.createArg().setValue("world");
|
||||||
|
task.setDir(new File(System.getProperty("user.dir")));
|
||||||
|
task.setRemotedir(new File("/tmp/foo"));
|
||||||
|
task.setFork(true);
|
||||||
|
task.setJvm(System.getProperty("java.home") + "/bin/java");
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled = false, groups = { "live" })
|
||||||
|
public void testSsh() throws NumberFormatException, FileNotFoundException, IOException {
|
||||||
|
String sshHost = System.getProperty("jclouds.test.ssh.host");
|
||||||
|
String sshPort = System.getProperty("jclouds.test.ssh.port");
|
||||||
|
String sshUser = System.getProperty("jclouds.test.ssh.username");
|
||||||
|
String sshPass = System.getProperty("jclouds.test.ssh.password");
|
||||||
|
String sshKeyFile = System.getProperty("jclouds.test.ssh.keyfile");
|
||||||
|
|
||||||
|
int port = (sshPort != null) ? Integer.parseInt(sshPort) : 22;
|
||||||
|
InetAddress host = (sshHost != null) ? InetAddress.getByName(sshHost) : InetAddress
|
||||||
|
.getLocalHost();
|
||||||
|
|
||||||
|
JavaOverSsh task = createTask();
|
||||||
|
task.setHost(host.getHostAddress());
|
||||||
|
task.setPort(port);
|
||||||
|
task.setTrust(true);
|
||||||
|
task.setUsername(sshUser);
|
||||||
|
if (sshKeyFile != null && !sshKeyFile.trim().equals("")) {
|
||||||
|
task.setKeyfile(sshKeyFile);
|
||||||
|
} else {
|
||||||
|
task.setPassword(sshPass);
|
||||||
|
}
|
||||||
|
task.setOutputproperty("out");
|
||||||
|
task.setErrorProperty("err");
|
||||||
|
task.setResultProperty("result");
|
||||||
|
task.execute();
|
||||||
|
assertEquals(task.getProject().getProperty("out"), "[hello, world]\n");
|
||||||
|
assertEquals(task.getProject().getProperty("err"), "err\n");
|
||||||
|
assertEquals(task.getProject().getProperty("result"), "3");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.jclouds.tools.ant;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class TestClass {
|
||||||
|
public static void main(String... args) {
|
||||||
|
File cwd = new File(System.getProperty("user.dir"));
|
||||||
|
System.out.println("children:");
|
||||||
|
for (File child : cwd.listFiles())
|
||||||
|
System.out.println(" " + child);
|
||||||
|
System.out.println("what you wrote:");
|
||||||
|
System.out.println(Arrays.asList(args));
|
||||||
|
System.err.println("this is the error stream");
|
||||||
|
System.out.println("will exit 3:");
|
||||||
|
System.exit(3);
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,7 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>ant-plugin</module>
|
<module>ant-plugin</module>
|
||||||
<module>getpath</module>
|
<module>getpath</module>
|
||||||
|
<module>antcontrib</module>
|
||||||
<module>vfs</module>
|
<module>vfs</module>
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
||||||
|
|
Loading…
Reference in New Issue