Introduction
Remote Ant provides a relatively painless way to integrate remote build functionality into CruiseControl. It handles the transfering of files to and from the remote servers, and supports built-in, synchronous, logging.
So what is different about this tool compared to the Ant-Contrib remote Ant? Well, to be honest, this code was written before the Ant-Contrib project's, so I haven't actually used theirs. I did have a quick snoop around their code, though. I believe that they are using sockets directly to implement their server, where I use RMI. This means that, for better of for worse, my own implementation uses the standard RMI security model - so you can closely control the access a remote build enjoys.
RMI also provided me an easy method of two way communication. I took advantage of this by creating an Ant listner which forwards build events back to the local machine in real time. The end result is that you can monitor the build as it is happening, regardless of where it is happening. You don't have to wait for the remote build to complete and grab the results all at once.
I also have a watchdog timer associated with easch session, so failed builds will be automatically cleaned up if the session is not closed properly.
I had put this code on the shelf when I noticed the Ant-Contrib project, but it seems there is still some demand for the synchronous logging feature, and I don't think any other solution exists for this at the moment, so I've decided to dust this off and present it here in the hopes that others may find it useful. Be warned, though, the code is pretty much as I left it two years ago, and probably could use some cleaning up.
NOTE: Until further notice, you must set the "uselogger" attribute to "false" in order for this to work with newer versions of Ant. See the comments section for more detatils
Installation
To incorporate Remote Ant support into your builds, please follow the following steps.
Downloading the software
You may either download the sources or grab a copy of the two jar files - ant-remote.jar and ant-remote-launcher.jar. The source package contains a simple Ant script to produce the needed jars. It also contains project files for Eclipse 3.x. Note: You will also need a copy of log4j.jar, which is contained in both the CruiseControl distribution and the source project available above.
Installing on the local machine
This is the easy part. On the machine upon which CruiseControl runs, simply copy ant-remote.jar into the lib directory of your chosen Ant installation. That's it!
If you do not wish to do this, you can also choose to place the jar elsewhere. Just be certain to set the appropriate classpath in your Ant script's taskdef element.
Installing on remote machines
Not as hard as it seems. If there is enough interest, I'll create an installer to ease the pain.
- Make certain that Java and Ant are installed on the machine.
- Create a directory into which you wish to install the Remote Ant server and copy the jar files (along with log4j.jar) into this directory. I recomend the following layout:
- Decide the port number upon which you wish to run the RMI registry. By default, this will be port 1099.
- Decide where in the file system you wish session context to be stored. I recommend the structure presented above. Also decide if any other directories should be accessible to the build.
- Create a policy file (I recomend policy.txt) in your installation directory. You will need to allow access for the Remote Ant code to connect to the port, read from the Ant installation location, and have full access to the session directory. If you wish to allow access to other directories, these will need their own entries as well. Here is an example policy file for Windows, assuming Remote Ant was installed as shown above on the D: drive:
- Create a log4j.properties file in your installation directory. I use:
- Create a simple launcher script. The Ant style launcher takes most of the pain out of this. The only manditory bits are the security policy file and root directory for session storage.
Caveots:
- If you do not have the ANT_HOME variable defined, you will also need to provide the location using "-Dant.home=/path/to/Ant".
- If you do not wish to use port 1099, you must add the switch "-port ####". This value must match what you used in your policy file.
- The default time to live for sessions is 240 minutes. If you wish to alter this default, you may use the switch "-ttl ###". The time is specified in minutes.
Using Remote Ant
Fire up the RemoteAnt server on each machine with which you wish to communicate. Note that I'm using port 1066 here. You should see something like:
You interact with the remote servers using a series of Ant tasks. Given the build file:
<project name="testremote" default="localtask">
<target name="localtask">
<!-- load our Remote Ant tasks -->
<taskdef resource="com/rjmpsmith/ant/taskdefs.properties"/>
<!-- Create a session on the remote machine -->
<createremotesession host="W1CSB257"
port="1066"
ttl="2"
property="session"/>
<!-- Copy this build script to the remote machine -->
<putremotefile session="${session}">
<fileset dir="." includes="build.xml"/>
</putremotefile>
<echo>Still on local machine</echo>
<!-- Launch the remote build -->
<remotebuild session="${session}"
targets="remotetask"/>
<echo>Back to the local machine</echo>
<!-- Retrieve a file from the remote machine -->
<getremotefile session="${session}"
remotefile="remote.txt"
localfile="results/remote.txt"/>
<!-- Shut down our session -->
<closeremotesession session="${session}"/>
<!-- Show the contents of our file -->
<concat>
<filelist dir="results" files="remote.txt"/>
</concat>
</target>
<target name="remotetask">
<echo>I'm on the remote machine!</echo>
<echo>Let's generate a file...</echo>
<echo file="remote.txt">This file was generated on the remote machine</echo>
</target>
</project>
You would get the result:
When I run remoteant.bat on the remote server (with the port changed to match my needs), and then run my script to start the remote build from my local machine, I get the following:
D:\workspace\test\Source\build>ant -f remote-test.xml -Djava.security.policy=policy.txt remote-test
Buildfile: remote-test.xml
[iwx-tpj] Jar Registry version dir 'D:\workspace\test\Source\build\..\jar-regi
stry\adobe\acrobat\ver1.1' has a 'consigned' subfolder but no info.txt file
remote-test:
[createremotesession] Created remote session: denpebuild02:192.168.235.108:20060
805130249
[putremotefile] Transfering 1 files to denpebuild02
[remotebuild] Building on denpebuild02 using remote-build.xml
denpebuild02.remotetask:
[denpebuild02.echo] BASEDIR=C:\REMOTE~1\sessions\192.168.235.108\20060805130249[remotebuild] Error unmarshaling return; nested exception is:
[remotebuild] java.lang.ClassNotFoundException: com.wgc.worx.common.exception.
ShouldNotHappenException (no security manager: RMI class loader disabled)
How do I fix this?