/** * Assign a ${@link Queue.Executable} to this OneShotSlave. By design, only one Queue.Executable * can be assigned, then slave is shut down. This method has to be called just as the ${@link Run} * as been created. It run the actual launch of the executor and use Run's ${@link * hudson.model.BuildListener} as computer launcher listener to collect the startup log as part of * the build. * * <p>Delaying launch of the executor until the Run is actually started allows to fail the build * on launch failure, so we have a strong 1:1 relation between a Run and it's Executor. * * @param listener */ synchronized void provision(TaskListener listener) { if (executable != null) { // already provisioned return; } final Executor executor = Executor.currentExecutor(); if (executor == null) { throw new IllegalStateException("running task without associated executor thread"); } try { realLauncher.launch(this.getComputer(), listener); if (getComputer().isActuallyOffline()) { provisionFailed(new IllegalStateException("Computer is offline after launch")); } } catch (Exception e) { provisionFailed(e); } executable = executor.getCurrentExecutable(); }
/** * Launches the slave agent for the given {@link Computer}. * * <p>If the slave agent is launched successfully, {@link SlaveComputer#setChannel(InputStream, * OutputStream, OutputStream, Listener)} should be invoked in the end to notify Hudson of the * established connection. The operation could also fail, in which case there's no need to make * any callback notification, (except to notify the user of the failure through {@link * StreamTaskListener}.) * * <p>This method must operate synchronously. Asynchrony is provided by {@link * Computer#connect(boolean)} and its correct operation depends on this. * * @param listener The progress of the launch, as well as any error, should be sent to this * listener. * @throws IOException if the method throws an {@link IOException} or {@link * InterruptedException}, the launch was considered a failure and the stack trace is reported * into the listener. This handling is just so that the implementation of this method doesn't * have to dilligently catch those exceptions. */ public void launch(SlaveComputer computer, TaskListener listener) throws IOException, InterruptedException { // to remain compatible with the legacy implementation that overrides the old signature launch(computer, cast(listener)); }