Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Hudson slaves run plugins?

We have a custom plugin for Hudson which uploads the output of a build onto a remote machine. We have just started looking into using a Hudson slave to improve throughput of builds, but the projects which use the custom plugin are failing to deploy with FileNotFoundExceptions.

From what we can see, the plugin is being run on the master even when the build is happening on the slave. The file that is not being found does exist on the slave but not on the master.

Questions:

  1. Can plugins be run on slaves? If so, how? Is there a way to identify a plugin as being 'serializable'? If Hudson slaves can't run plugins, how does the SVN checkout happen?
  2. Some of the developers here think that the solution to this problem is to make the Hudson master's workspace a network drive and let the slave use that same workspace - is this as bad an idea as it seems to me?
like image 431
Rich Avatar asked Feb 14 '12 15:02

Rich


1 Answers

Firstly, go Jenkins! ;)

Secondly, you are correct — the code is being executed on the master. This is the default behaviour of a Hudson/Jenkins plugin.

When you want to run code on a remote node, you need to get a reference to that node's VirtualChannel, e.g. via the Launcher that's probably passed into your plugin's main method.

The code to be run on the remote node should be encapsulated in a Callable — this is the part that needs to be serialisable, as Jenkins will automagically serialise it, pass it to the node via its channel, execute it and return the result.

This also hides the distinction between master and slave — even if the build is actually running on the master, the "callable" code will transparently run on the correct machine.

For example:

@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
                       BuildListener listener) {
    // This method is being run on the master...

    // Define what should be run on the slave for this build
    Callable<String, IOException> task = new Callable<String, IOException>() {
        public String call() throws IOException {
            // This code will run on the build slave
            return InetAddress.getLocalHost().getHostName();
        }
    };

    // Get a "channel" to the build machine and run the task there
    String hostname = launcher.getChannel().call(task);

    // Much success...
}

See also FileCallable, and check out the source code of other Jenkins plugins with similar functionality.

I would recommend making your plugin work properly rather than using the network share solution.. :)

like image 75
Christopher Orr Avatar answered Oct 14 '22 01:10

Christopher Orr