@Override public void afterDisconnect(SlaveComputer computer, TaskListener listener) { try { JIDefaultAuthInfoImpl auth = createAuth(); JISession session = JISession.createSession(auth); session.setGlobalSocketTimeout(60000); SWbemServices services = WMI.connect(session, computer.getName()); Win32Service slaveService = services.getService("jenkinsslave"); if (slaveService != null) { listener.getLogger().println(Messages.ManagedWindowsServiceLauncher_StoppingService()); slaveService.StopService(); } // destroy session to free the socket JISession.destroySession(session); } catch (UnknownHostException e) { e.printStackTrace(listener.error(e.getMessage())); } catch (JIException e) { e.printStackTrace(listener.error(e.getMessage())); } }
private void wmiLaunch(final EC2Computer computer, final TaskListener listener) throws IOException, InterruptedException, JIException { try { final PrintStream logger = listener.getLogger(); final String name = host; logger.println(Messages.ManagedWindowsServiceLauncher_ConnectingTo(name)); InetAddress host = InetAddress.getByName(name); try { Socket s = new Socket(); s.connect(new InetSocketAddress(host, 135), 5000); s.close(); } catch (IOException e) { logger.println( "Failed to connect to port 135 of " + name + ". Is Windows firewall blocking this port? Or did you disable DCOM service?"); // again, let it continue. } JIDefaultAuthInfoImpl auth = createAuth(); JISession session = JISession.createSession(auth); session.setGlobalSocketTimeout(60000); SWbemServices services = WMI.connect(session, name); String path = computer.getNode().getRemoteFS(); if (path.indexOf(':') == -1) throw new IOException( "Remote file system root path of the slave needs to be absolute: " + path); SmbFile remoteRoot = new SmbFile( "smb://" + name + "/" + path.replace('\\', '/').replace(':', '$') + "/", createSmbAuth()); if (!remoteRoot.exists()) remoteRoot.mkdirs(); try { // does Java exist? logger.println("Checking if Java exists"); WindowsRemoteProcessLauncher wrpl = new WindowsRemoteProcessLauncher(name, auth); Process proc = wrpl.launch("%JAVA_HOME%\\bin\\java -fullversion", "c:\\"); proc.getOutputStream().close(); IOUtils.copy(proc.getInputStream(), logger); proc.getInputStream().close(); int exitCode = proc.waitFor(); if (exitCode == 1) { // we'll get this error code if Java is not found logger.println("No Java found. Downloading JDK"); JDKInstaller jdki = new JDKInstaller("jdk-6u16-oth-JPR@CDS-CDS_Developer", true); URL jdk = jdki.locate(listener, Platform.WINDOWS, CPU.i386); listener.getLogger().println("Installing JDK"); copyStreamAndClose( jdk.openStream(), new SmbFile(remoteRoot, "jdk.exe").getOutputStream()); String javaDir = path + "\\jdk"; // this is where we install Java to WindowsRemoteFileSystem fs = new WindowsRemoteFileSystem(name, createSmbAuth()); fs.mkdirs(javaDir); jdki.install( new WindowsRemoteLauncher(listener, wrpl), Platform.WINDOWS, fs, listener, javaDir, path + "\\jdk.exe"); } } catch (Exception e) { e.printStackTrace(listener.error("Failed to prepare Java")); } String id = generateServiceId(path); Win32Service slaveService = services.getService(id); if (slaveService == null) { logger.println(Messages.ManagedWindowsServiceLauncher_InstallingSlaveService()); if (!DotNet.isInstalled(2, 0, name, auth)) { // abort the launch logger.println(Messages.ManagedWindowsServiceLauncher_DotNetRequired()); return; } // copy exe logger.println(Messages.ManagedWindowsServiceLauncher_CopyingSlaveExe()); copyStreamAndClose( getClass().getResource("/windows-service/jenkins.exe").openStream(), new SmbFile(remoteRoot, "jenkins-slave.exe").getOutputStream()); copySlaveJar(logger, remoteRoot); // copy jenkins-slave.xml logger.println(Messages.ManagedWindowsServiceLauncher_CopyingSlaveXml()); String nodeNameEncoded = java.net.URLEncoder.encode(nodeName, "UTF-8").replace("+", "%20"); String xml = generateSlaveXml( id, "\"%JAVA_HOME%\\bin\\java\"", " -jnlpUrl " + Hudson.getInstance().getRootUrl() + "computer/" + nodeNameEncoded + "/slave-agent.jnlp"); copyStreamAndClose( new ByteArrayInputStream(xml.getBytes("UTF-8")), new SmbFile(remoteRoot, "jenkins-slave.xml").getOutputStream()); // install it as a service logger.println(Messages.ManagedWindowsServiceLauncher_RegisteringService()); Document dom = new SAXReader().read(new StringReader(xml)); Win32Service svc = services.Get("Win32_Service").cast(Win32Service.class); int r = svc.Create( id, dom.selectSingleNode("/service/name").getText() + " at " + path, path + "\\jenkins-slave.exe", Win32OwnProcess, 0, "Manual", true); if (r != 0) { throw new JIException(-1, ("Failed to create a service: " + svc.getErrorMessage(r))); } slaveService = services.getService(id); } else { copySlaveJar(logger, remoteRoot); } logger.println(Messages.ManagedWindowsServiceLauncher_StartingService()); slaveService.start(); // wait until we see the port.txt, but don't do so forever logger.println(Messages.ManagedWindowsServiceLauncher_WaitingForService()); SmbFile portFile = new SmbFile(remoteRoot, "port.txt"); for (int i = 0; !portFile.exists(); i++) { if (i >= 30) { throw new JIException(-1, Messages.ManagedWindowsServiceLauncher_ServiceDidntRespond()); } Thread.sleep(1000); } int p = readSmbFile(portFile); // connect logger.println(Messages.ManagedWindowsServiceLauncher_ConnectingToPort(p)); final Socket s = new Socket(name, p); // ready computer.setChannel( new BufferedInputStream(new SocketInputStream(s)), new BufferedOutputStream(new SocketOutputStream(s)), listener.getLogger(), new Listener() { @Override public void onClosed(Channel channel, IOException cause) { afterDisconnect(computer, listener); } }); // destroy session to free the socket JISession.destroySession(session); } catch (SmbException e) { e.printStackTrace(listener.error(e.getMessage())); } catch (DocumentException e) { e.printStackTrace(listener.error(e.getMessage())); } }