提交 9640d966 编写于 作者: K kohsuke

implemented a menu item to install a slave as a windows service

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@12406 71c3de6d-444a-0410-be80-ed276b4c234a
上级 c4c7cd06
......@@ -54,7 +54,7 @@ public class WindowsInstallerLink extends ManagementLink {
}
public String getDisplayName() {
return "Install as Windows Service";
return Messages.WindowsInstallerLink_DisplayName();
}
public String getDescription() {
......
package hudson.lifecycle;
import hudson.FilePath;
import hudson.Launcher.LocalLauncher;
import hudson.remoting.Callable;
import hudson.remoting.Engine;
import hudson.remoting.jnlp.MainDialog;
import hudson.remoting.jnlp.MainMenu;
import hudson.util.StreamTaskListener;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
/**
* @author Kohsuke Kawaguchi
*/
public class WindowsSlaveInstaller implements Callable<Void,RuntimeException>, ActionListener {
/**
* Root directory of this slave.
* String, not File because the platform can be different.
*/
private final String rootDir;
private transient Engine engine;
private transient MainDialog dialog;
public WindowsSlaveInstaller(String rootDir) {
this.rootDir = rootDir;
}
public Void call() {
if(File.separatorChar=='/') return null; // not Windows
if(System.getProperty("hudson.showWindowsServiceInstallLink")==null)
return null; // only show this when it makes sense, which is when we run from JNLP
dialog = MainDialog.get();
if(dialog==null) return null; // can't find the main window. Maybe not running with GUI
// capture the engine
engine = Engine.current();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainMenu mainMenu = dialog.getMainMenu();
JMenu m = mainMenu.getFileMenu();
JMenuItem menu = new JMenuItem(Messages.WindowsInstallerLink_DisplayName(), KeyEvent.VK_W);
menu.addActionListener(WindowsSlaveInstaller.this);
m.add(menu);
mainMenu.commit();
}
});
return null;
}
/**
* Called when the install menu is selected
*/
public void actionPerformed(ActionEvent e) {
int r = JOptionPane.showConfirmDialog(dialog,
"This will install a slave agent as a Windows service,\n" +
"so that this slave will connect to Hudson as soon as the machine boots.\n" +
"Do you want to proceed with installation?",
Messages.WindowsInstallerLink_DisplayName(),
JOptionPane.OK_CANCEL_OPTION);
if(r!=JOptionPane.OK_OPTION) return;
final File dir = new File(rootDir);
try {
final File slaveExe = new File(dir, "hudson-slave.exe");
FileUtils.copyURLToFile(getClass().getResource("/windows-service/hudson.exe"), slaveExe);
// write out the descriptor
String xml = IOUtils.toString(getClass().getResourceAsStream("/windows-service/hudson-slave.xml"), "UTF-8");
xml = xml.replace("@JAVA@",System.getProperty("java.home")+"\\bin\\java.exe");
URL jnlp = new URL(new URL(engine.hudsonUrl),"../computer/"+engine.slaveName+"/slave-agent.jnlp");
xml = xml.replace("@URL@",jnlp.toExternalForm());
FileUtils.writeStringToFile(new File(dir, "hudson-slave.xml"),xml,"UTF-8");
// copy slave.jar
URL slaveJar = new URL(new URL(engine.hudsonUrl),"../jnlpJars/remoting.jar");
File dstSlaveJar = new File(dir,"slave.jar").getCanonicalFile();
if(!dstSlaveJar.exists()) // perhaps slave.jar is already there?
FileUtils.copyURLToFile(slaveJar,dstSlaveJar);
// install as a service
ByteArrayOutputStream baos = new ByteArrayOutputStream();
StreamTaskListener task = new StreamTaskListener(baos);
r = new LocalLauncher(task).launch(new String[]{slaveExe.getPath(), "install"}, new String[0], task.getLogger(), new FilePath(dir)).join();
if(r!=0) {
JOptionPane.showMessageDialog(
dialog,baos.toString(),"Error",
JOptionPane.ERROR_MESSAGE);
return;
}
r = JOptionPane.showConfirmDialog(dialog,
"Installation was successful. Would you like to\n" +
"Stop this slave agent and start the newly installed service?",
Messages.WindowsInstallerLink_DisplayName(),
JOptionPane.OK_CANCEL_OPTION);
if(r!=JOptionPane.OK_OPTION) return;
// let the service start after we close our connection, to avoid conflicts
Runtime.getRuntime().addShutdownHook(new Thread("service starter") {
public void run() {
try {
StreamTaskListener task = new StreamTaskListener(System.out);
int r = new LocalLauncher(task).launch(new String[]{slaveExe.getPath(), "start"}, new String[0], task.getLogger(), new FilePath(dir)).join();
task.getLogger().println(r==0?"Successfully started":"start service failed. Exit code="+r);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.exit(0);
} catch (Exception t) {
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
JOptionPane.showMessageDialog(
dialog,sw.toString(),"Error",
JOptionPane.ERROR_MESSAGE);
}
}
private static final long serialVersionUID = 1L;
}
......@@ -9,6 +9,7 @@ import hudson.util.StreamTaskListener;
import hudson.util.NullStream;
import hudson.util.RingBufferLogHandler;
import hudson.FilePath;
import hudson.lifecycle.WindowsSlaveInstaller;
import hudson.maven.agent.Main;
import hudson.maven.agent.PluginManagerInterceptor;
......@@ -201,8 +202,8 @@ public final class SlaveComputer extends Computer {
Boolean _isUnix = channel.call(new DetectOS());
log.println(_isUnix? hudson.model.Messages.Slave_UnixSlave():hudson.model.Messages.Slave_WindowsSlave());
// install log handler
channel.call(new LogInstaller());
channel.call(new WindowsSlaveInstaller(getNode().getRemoteFS()));
// update the data structure atomically to prevent others from seeing a channel that's not properly initialized yet
synchronized(channelLock) {
......
WindowsInstallerLink.DisplayName=Install as Windows Service
\ No newline at end of file
......@@ -33,6 +33,7 @@
</j:otherwise>
</j:choose>
<jar href="${rootURL}jnlpJars/remoting.jar"/>
<property name="hudson.showWindowsServiceInstallLink" value="true" />
</resources>
<application-desc main-class="hudson.remoting.jnlp.Main">
......
<!--
Windows service definition for Hudson slave
To uninstall, run "hudson-slave.exe stop" to stop the service, then "hudson-slave.exe uninstall" to uninstall the service.
Both commands don't produce any output if the execution is successful.
-->
<service>
<id>hudsonslave</id>
<name>Hudson Slave</name>
<description>This service runs a slave for Hudson continous integration system.</description>
<!--
if you'd like to run Hudson with a specific version of Java, specify a full path to java.exe.
The following value assumes that you have java in your PATH.
-->
<executable>@JAVA@</executable>
<arguments>-jar "%BASE%\slave.jar" -jnlpUrl @URL@</arguments>
</service>
......@@ -15,5 +15,4 @@
-->
<executable>java</executable>
<arguments>-Xmx256m -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar "%BASE%\hudson.war" --httpPort=8080</arguments>
<interactive />
</service>
package hudson.remoting.jnlp;
import hudson.remoting.Engine;
import javax.swing.*;
import java.awt.*;
......@@ -62,4 +64,15 @@ public class MainDialog extends JFrame {
public void status(String msg) {
statusLabel.setText(msg);
}
/**
* If the current JVM runs a {@link MainDialog} as a JNLP slave agent,
* return its reference, otherwise null.
*/
public static MainDialog get() {
Engine e = Engine.current();
if(e==null) return null;
if (!(e.listener instanceof GuiListener)) return null;
return ((GuiListener) e.listener).frame;
}
}
......@@ -37,8 +37,9 @@ public final class MainMenu extends JMenuBar {
repaint();
if(getComponentCount()>0) {
owner.setJMenuBar(this);
owner.invalidate();
owner.repaint();
// work around for paint problem. see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4949810
if(owner.isVisible())
owner.setVisible(true);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册