use of hudson.lifecycle.WindowsSlaveInstaller in project hudson-2.x by hudson.
the class SlaveComputer method setChannel.
/**
* Creates a {@link Channel} from the given stream and sets that to this slave.
*
* @param in
* Stream connected to the remote "slave.jar". It's the caller's responsibility to do
* buffering on this stream, if that's necessary.
* @param out
* Stream connected to the remote peer. It's the caller's responsibility to do
* buffering on this stream, if that's necessary.
* @param launchLog
* If non-null, receive the portion of data in <tt>is</tt> before
* the data goes into the "binary mode". This is useful
* when the established communication channel might include some data that might
* be useful for debugging/trouble-shooting.
* @param listener
* Gets a notification when the channel closes, to perform clean up. Can be null.
* By the time this method is called, the cause of the termination is reported to the user,
* so the implementation of the listener doesn't need to do that again.
*/
public void setChannel(InputStream in, OutputStream out, OutputStream launchLog, Channel.Listener listener) throws IOException, InterruptedException {
if (this.channel != null)
throw new IllegalStateException("Already connected");
final TaskListener taskListener = new StreamTaskListener(launchLog);
PrintStream log = taskListener.getLogger();
Channel channel = new Channel(nodeName, threadPoolForRemoting, Channel.Mode.NEGOTIATE, in, out, launchLog);
channel.addListener(new Channel.Listener() {
@Override
public void onClosed(Channel c, IOException cause) {
SlaveComputer.this.channel = null;
// Orderly shutdown will have null exception
if (cause != null) {
offlineCause = new ChannelTermination(cause);
cause.printStackTrace(taskListener.error("Connection terminated"));
} else {
taskListener.getLogger().println("Connection terminated");
}
launcher.afterDisconnect(SlaveComputer.this, taskListener);
}
});
if (listener != null)
channel.addListener(listener);
String slaveVersion = channel.call(new SlaveVersion());
log.println("Slave.jar version: " + slaveVersion);
boolean _isUnix = channel.call(new DetectOS());
log.println(_isUnix ? hudson.model.Messages.Slave_UnixSlave() : hudson.model.Messages.Slave_WindowsSlave());
String defaultCharsetName = channel.call(new DetectDefaultCharset());
String remoteFs = getNode().getRemoteFS();
if (_isUnix && !remoteFs.contains("/") && remoteFs.contains("\\"))
log.println("WARNING: " + remoteFs + " looks suspiciously like Windows path. Maybe you meant " + remoteFs.replace('\\', '/') + "?");
FilePath root = new FilePath(channel, getNode().getRemoteFS());
channel.call(new SlaveInitializer());
channel.call(new WindowsSlaveInstaller(remoteFs));
for (ComputerListener cl : ComputerListener.all()) cl.preOnline(this, channel, root, taskListener);
offlineCause = null;
// update the data structure atomically to prevent others from seeing a channel that's not properly initialized yet
synchronized (channelLock) {
if (this.channel != null) {
// check again. we used to have this entire method in a big sycnhronization block,
// but Channel constructor blocks for an external process to do the connection
// if CommandLauncher is used, and that cannot be interrupted because it blocks at InputStream.
// so if the process hangs, it hangs the thread in a lock, and since Hudson will try to relaunch,
// we'll end up queuing the lot of threads in a pseudo deadlock.
// This implementation prevents that by avoiding a lock. HUDSON-1705 is likely a manifestation of this.
channel.close();
throw new IllegalStateException("Already connected");
}
isUnix = _isUnix;
numRetryAttempt = 0;
this.channel = channel;
defaultCharset = Charset.forName(defaultCharsetName);
}
for (ComputerListener cl : ComputerListener.all()) cl.onOnline(this, taskListener);
log.println("Slave successfully connected and online");
Hudson.getInstance().getQueue().scheduleMaintenance();
}
Aggregations