Dashboard > CruiseControl > Home > RobertsRemoteAnt
RobertsRemoteAnt Log In | Sign Up   View a printable version of the current page.

Added by Robert J. Smith , last edited by Robert J. Smith on Feb 24, 2006  (view change)
Labels: 
(None)

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.

  1. Make certain that Java and Ant are installed on the machine.
  2. 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:
    \|
    +- RemoteAnt/
        \|
        +- lib/
        \|   +- ant-remote.jar
        \|   +- ant-remote-launcher.jar
        \|   +- log4j.jar
        \|
        +- sessions/
        \|
        +- policy.txt  (Java security policy file)
        +- log4j.properties  (for logging)
        +- remoteant.bat / remoteant.sh  (launching script)
    
  3. Decide the port number upon which you wish to run the RMI registry. By default, this will be port 1099.
  4. 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.
  5. 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:
    "policy.txt"
    grant {
        //File permissions
        permission java.io.FilePermission "D:\\RemoteAnt\\sessions\\-", "read, write, delete";
        permission java.io.FilePermission "D:\\apache-ant-1.6.2\\-", "read";
        //Socket permissions
        permission java.net.SocketPermission "*:1099-",
            "connect,accept,resolve";
        //Property premissions
        permission java.util.PropertyPermission "*", "read, write";
    }; 
    
  6. Create a log4j.properties file in your installation directory. I use:
    "log4j.properties"
    log4j.rootCategory=INFO,A1,FILE
    
    # A1 is to console
    log4j.appender.A1=org.apache.log4j.ConsoleAppender
    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
    log4j.appender.A1.layout.ConversionPattern=[RemoteAnt] %d{MMM-dd HH:mm:ss} %-16c{1}- %m%n
    
    # FILE is file logger with rotation
    log4j.appender.FILE=org.apache.log4j.RollingFileAppender
    log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
    log4j.appender.FILE.layout.ConversionPattern=%d [%-9t] %-5p %-16c{1} %x- %m%n
    log4j.appender.FILE.File=remoteant.log
    log4j.appender.FILE.MaxFileSize=5000KB
    log4j.appender.FILE.MaxBackupIndex=4
    
  7. 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.
    "remoteant.bat"
    javaw -Djava.security.policy=policy.txt -jar lib\ant-remote-launcher.jar -root D:\RemoteAnt\sessions
    

    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:

D:\RemoteAnt>java -Djava.security.policy=policy.txt -jar lib\ant-remote-launcher.jar
-port 1066 -root D:\RemoteAnt\sessions
[RemoteAnt] Jun-13 18:11:15 RemoteAntServer - Using Ant from D:\apache-ant-1.6.2

[RemoteAnt] Jun-13 18:11:15 RemoteAntServer - RemoteAnt installation is at D:\RemoteAnt
[RemoteAnt] Jun-13 18:11:15 RemoteAntServer - File storage root is set to D:\RemoteAnt\sessions
[RemoteAnt] Jun-13 18:11:15 RemoteAntServer - Default time to live for sessions is 240 minutes.
[RemoteAnt] Jun-13 18:11:15 RemoteAntServer - Starting server on host W1CSB257 port 1066.
[RemoteAnt] Jun-13 18:11:15 RemoteAntServer - Bound rmi://W1CSB257:1066/RemoteBuildServices

You interact with the remote servers using a series of Ant tasks. Given the build file:

"build.xml"
<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:

D:\test>ant
Buildfile: build.xml

localtask:
[createremotesession] Created remote session: W1CSB257:192.168.110.178:200551371454
      [putremotefile] Transfering 1 files to W1CSB257
               [echo] Still on local machine
        [remotebuild] Building on W1CSB257 using build.xml

W1CSB257.remotetask:
[W1CSB257.echo] I'm on the remote machine!
[W1CSB257.echo] Let's generate a file...

localtask:
              [echo] Back to the local machine
     [getremotefile] Recieving remote.txt from W1CSB257
     [getremotefile] Copied remote.txt from W1CSB257 to results/remote.txt
[closeremotesession] Session W1CSB257:192.168.110.178:200551371454 closed.
            [concat] This file was generated on the remote machine

BUILD SUCCESSFUL
Total time: 1 second
D:\test>

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?

Powered by a free Atlassian Confluence Open Source Project / Non-profit License granted to ThoughtWorks, Inc.. Evaluate Confluence today.
Powered by Atlassian Confluence 2.7.1, the Enterprise Wiki. Bug/feature request - Atlassian news - Contact administrators