Author: chatellier Date: 2008-12-23 11:24:23 +0000 (Tue, 23 Dec 2008) New Revision: 1720 Added: isis-fish/trunk/TODO.txt Modified: isis-fish/trunk/pom.xml isis-fish/trunk/src/main/java/fr/ifremer/isisfish/IsisConfig.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/actions/VCSAction.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/datastore/SimulationStorage.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SshSimulatorLauncher.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java isis-fish/trunk/src/main/resources/i18n/isis-fish-en_GB.properties isis-fish/trunk/src/main/resources/i18n/isis-fish-fr_FR.properties Log: Modification du launcher de simulation sur Caparmor Added: isis-fish/trunk/TODO.txt =================================================================== --- isis-fish/trunk/TODO.txt (rev 0) +++ isis-fish/trunk/TODO.txt 2008-12-23 11:24:23 UTC (rev 1720) @@ -0,0 +1,10 @@ +TODO au 22/12/2008 +================== + + - refaire les UI des résultats + - tester que les paramêtres d'une simulation + sont corrects + (ex:detection qu'il n'y a pas de strategie) + - modification des configurations des paths + pour les lancements à distance (caparmor...) + - simulation path... \ No newline at end of file Modified: isis-fish/trunk/pom.xml =================================================================== --- isis-fish/trunk/pom.xml 2008-12-22 15:59:12 UTC (rev 1719) +++ isis-fish/trunk/pom.xml 2008-12-23 11:24:23 UTC (rev 1720) @@ -101,6 +101,13 @@ <version>1.8.0</version> <scope>compile</scope> </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>1.4</version> + <scope>compile</scope> + </dependency> <dependency> <groupId>org.jdesktop</groupId> Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/IsisConfig.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/IsisConfig.java 2008-12-22 15:59:12 UTC (rev 1719) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/IsisConfig.java 2008-12-23 11:24:23 UTC (rev 1720) @@ -67,7 +67,8 @@ /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(IsisConfig.class); - /** la version du logiciel constitue de l.d.a.r + /** + * La version du logiciel constitue de l.d.a.r * <li>l: le numero de version du logiciel * <li>d: le numero de version du schema de la base de donnees * <li>a: le numero de version de l'api des scripts @@ -268,42 +269,55 @@ String result = getOption(Option.SIMULATOR_SSH_USER_NAME.key); return result; } - + /** - * Retourne le mot de passe pour acceder au serveur de simulation accessible via SSH. + * Retourne le chemin complet du jar. * - * @return simulator password + * @return simulator jar path */ - public String getSimulatorSshPassword() { - String result = getOption(Option.SIMULATOR_SSH_PASSWORD.key); + public String getSimulatorSshJarPath() { + String result = getOption(Option.SIMULATOR_SSH_JARPATH.key); return result; } /** - * Retourne la clé privée pour acceder au serveur de simulation accessible via SSH. + * Retourne le chemin relatif ou abs du repertoire + * root des données d'isis. * - * @return simulator password + * @return simulator data path */ - public String getSimulatorSshPrivateKey() { - String result = getOption(Option.SIMULATOR_SSH_PRIVATEKEY.key); + public String getSimulatorSshDataPath() { + String result = getOption(Option.SIMULATOR_SSH_DATAPATH.key); return result; } /** + * Retourne la clé privée de l'utilisteur courant. + * + * @return private ssh key path + */ + public File getSSHPrivateKeyFilePath() { + File result = getOptionAsFile(Option.SSH_KEY_FILE.key); + return result; + } + + /* * Le type de simulation par defaut a utiliser (local, remote, ...) * @return - */ + *) public boolean isSimulatorLocal() { + // FIXME never called String value = getOption(Option.SIMULATOR_LAUNCHER.key); + // and following code always return false : boolean result = "local".equalsIgnoreCase(value); return result; - } + }*/ -// public boolean isUseVCS() { -// String value = getOption(Option.VCS_TYPE.key); -// boolean result = !VCSNone.TYPE_NONE.equals(value); -// return result; -// } + /*public boolean isUseVCS() { + String value = getOption(Option.VCS_TYPE.key); + boolean result = !VCSNone.TYPE_NONE.equals(value); + return result; + }*/ public boolean isLaunchUI() { boolean result = getOptionAsBoolean(Option.LAUNCH_UI.key); @@ -596,7 +610,12 @@ // Toutes les options disponibles ////////////////////////////////////////////////// - static public enum Option { + /** + * Options. + * + * Set it protected to force getOption() call. + */ + protected static enum Option { COMPILATION_DIRECTORY("compilation.directory", _("isisfish.config.main.compileDirectory.description"), getUserHome() + File.separator + "isis-build"), CONFIG_FILE(CONFIG_FILE_NAME, _("isisfish.config.main.configFileName.description"), CONFIG_FILENAME), @@ -614,7 +633,7 @@ /** prevu pour l'architecture de lancement en plugin: local, isis-server, caparmor, ... */ SIMULATOR_LAUNCHER(SimulationService.SIMULATION_LAUNCHER + ".localDefault", _("isisfish.config.main.localSimulator.description"), InProcessSimulatorLauncher.class.getName()), SIMULATOR_LAUNCHER_SUB(SimulationService.SIMULATION_LAUNCHER + ".subDefault", _("isisfish.config.main.subSimulator.description"), SubProcessSimulationLauncher.class.getName()), - // SIMULATOR_LAUNCHER_REMOTE(SimulationService.SIMULATION_LAUNCHER + ".remoteDefault", _("isisfish.config.main.remoteSimulator.description"), SshSimulatorLauncher.class.getName()), + SIMULATOR_LAUNCHER_REMOTE(SimulationService.SIMULATION_LAUNCHER + ".remoteCaparmor", _("isisfish.config.main.remoteCaparmor.description"), SshSimulatorLauncher.class.getName()), SIMULATOR_SERVER("simulation.server", _("isisfish.config.main.simulationServer.description"), "http://simulateur.ifremer.fr:9090"), /** le login a utiliser pour les launcher distant, le type du launcher est ajouter a la cle (car 1 login par launcher) */ @@ -625,22 +644,23 @@ SIMULATOR_SSH_SERVER("simulation.ssh.server", _("isisfish.config.main.simulation.ssh.server.description"), "caparmor.ifremer.fr:22"), /** Serveur accessible par ssh : login */ SIMULATOR_SSH_USER_NAME("simulation.ssh.username", _("isisfish.config.main.simulation.ssh.login.description"), "isisfish"), - /** Serveur accessible par ssh : password */ - SIMULATOR_SSH_PASSWORD("simulation.ssh.password", _("isisfish.config.main.simulation.ssh.password.description"), ""), - /** Serveur accessible par ssh : cle privee */ - SIMULATOR_SSH_PRIVATEKEY("simulation.ssh.privatekey", _("isisfish.config.main.simulation.ssh.privatekey.description"), getUserHome() + File.separator + ".ssh" + File.separator + "id_rsa"), - + /** Serveur accessible par ssh : remote data path */ + SIMULATOR_SSH_DATAPATH("simulation.ssh.datapath", _("isisfish.config.main.simulation.ssh.datapath.description"), "/home/" + SIMULATOR_SSH_USER_NAME.defaultValue + "/isis-database-3"), + /** Serveur accessible par SSH : chemin complet du jar depuis le /home une fois connecté */ + SIMULATOR_SSH_JARPATH("simulation.ssh.jarpath", _("isisfish.config.main.simulation.ssh.jarpath.description"), "./isis-fish-" + getVersion() + "/isis-fish-" + getVersion() + ".jar"), + LOCALE("locale", _("isisfish.config.main.locale.description"), "fr_FR"), -// REGION_MAP("regionMap", _("isisfish.config.main.regionMap.description"), "maps"), -// RESULT_EXPORT("resultExport", String.class, 15, n_("isisfish.config.main.resultExport.description"), "resultExports"), + // REGION_MAP("regionMap", _("isisfish.config.main.regionMap.description"), "maps"), + // RESULT_EXPORT("resultExport", String.class, 15, n_("isisfish.config.main.resultExport.description"), "resultExports"), SIMULATION_SHOW_ONLY_ERROR("simulationShowOnlyError", _("isisfish.config.main.simulationShowOnlyError.description"), "false"), -// SIMULATION_SHOW_ONLY_QUEUE("simulationShowOnlyQueue", _("isisfish.config.main.simulationShowOnlyQueue.description"), "true"), + // SIMULATION_SHOW_ONLY_QUEUE("simulationShowOnlyQueue", _("isisfish.config.main.simulationShowOnlyQueue.description"), "true"), // if false no graphical interface LAUNCH_UI("launch.ui", _("isisfish.config.main.launchUI.description"), "true"), DATABASE_DIRECTORY("database.directory", _("isisfish.config.vcs.localDatabasePath.description"), getUserHome() + File.separator + "isis-database-3"), + // TODO remove duplicated ssh key configuration SSH_KEY_FILE("ssh.key.file", _("isisfish.config.vcs.keyFile.description"), getUserHome() + File.separator + ".ssh" + File.separator + "isis_rsa"), SSH_PASSPHRASE_ENABLED("ssh.passphrase.enabled", _("isisfish.config.vcs.noPassPhrase.description"), "false"), SSH_PASSPHRASE("ssh.passphrase", _("isisfish.config.vcs.passphrase.description"), ""), @@ -655,15 +675,13 @@ VCS_USER_PASSWORD(VCS.VCS_USER_PASSWORD, _("isisfish.config.vcs.userPassword.description"), ""), VCS_HOST_NAME(VCS.VCS_HOST_NAME, _("isisfish.config.vcs.hostName.description"), "labs.libre-entreprise.org"), VCS_PATH(VCS.VCS_PATH, _("isisfish.config.vcs.remotePath.description"), "/svnroot/isis-fish-data/"), -// VCS_TAG(VCS.VCS_TAG, _("isisfish.config.vcs.remoteDatabase.description"), "/trunk"), -// TYPE_REPO_PROPERTY_KEY = newConfigPropertyKey("typeRepo", VCSTypeRepo.class, 9, n_("isisfish.config.vcs.typeRepo.description"), "TAG"), -// PROJECT_NAME_PROPERTY_KEY = newConfigPropertyKey("projectName", String.class, 11, n_("isisfish.config.main.projectName.description"), "Isis-Fish"), + // VCS_TAG(VCS.VCS_TAG, _("isisfish.config.vcs.remoteDatabase.description"), "/trunk"), + // TYPE_REPO_PROPERTY_KEY = newConfigPropertyKey("typeRepo", VCSTypeRepo.class, 9, n_("isisfish.config.vcs.typeRepo.description"), "TAG"), + // PROJECT_NAME_PROPERTY_KEY = newConfigPropertyKey("projectName", String.class, 11, n_("isisfish.config.main.projectName.description"), "Isis-Fish"), USER_NAME("user.name", _("isisfish.config.main.userName.description"), System.getProperty("user.name")), SMTP_SERVER("smtpServer", _("isisfish.config.main.smtpServer.description"), "smtp"), - USER_MAIL("userMail", _("isisfish.config.main.userMail.description"), USER_NAME.key + "@" + VCS_HOST_NAME.key), - - ; + USER_MAIL("userMail", _("isisfish.config.main.userMail.description"), USER_NAME.key + "@" + VCS_HOST_NAME.key); public final String key; public final String description; @@ -684,7 +702,7 @@ AfterInit, AfterInitVCS, AfterUI, BeforeExit } - static public enum Action { + public static enum Action { HELP(_("Show help"), OtherAction.class.getName() + "#help", "-h", "--help"), IMPORT_ANALYSE_PLAN(_(""), ImportAction.class.getName() + "#importAnalysePlan", "--importAnalysePlan"), Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/actions/VCSAction.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/actions/VCSAction.java 2008-12-22 15:59:12 UTC (rev 1719) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/actions/VCSAction.java 2008-12-23 11:24:23 UTC (rev 1720) @@ -49,7 +49,7 @@ } public void sshCreateKey(boolean force) throws Exception { - File f = config.getOptionAsFile(IsisConfig.Option.SSH_KEY_FILE.key); + File f = config.getSSHPrivateKeyFilePath(); if (f.exists() && !force) { log.error("the private key already exist " + f + ", use option [force] to overwrite"); @@ -64,7 +64,7 @@ String openSshPublicKey = SshKeyGenerator.convertPublicKeyFile(publicKeyFile, new OpenSSHPublicKeyFormat( - config.getOption(IsisConfig.Option.USER_NAME.key) + + config.getUserName() + "@forIsisFish 1024-bit rsa")); log.info("public key OpenSsh : " + openSshPublicKey); Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/datastore/SimulationStorage.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/datastore/SimulationStorage.java 2008-12-22 15:59:12 UTC (rev 1719) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/datastore/SimulationStorage.java 2008-12-23 11:24:23 UTC (rev 1720) @@ -121,7 +121,7 @@ * @param name le nom de la simulation dont on souhaite le repertoire * @return */ - static public File getSimulationDirectory(String name) { + public static File getSimulationDirectory(String name) { File result = getSimulationDirectory(); result = new File(result, name); if (!result.exists()) { @@ -204,7 +204,7 @@ * externe de connaitre l'etat d'une simulation distante * @return */ - static protected File getSimulationControlFile(String id) { + protected static File getSimulationControlFile(String id) { File result = new File(getSimulationDirectory(id), "control"); return result; } @@ -230,17 +230,30 @@ /** * Reli le fichier contenant les infos de SimulationControl, en excluant - * certain champs - * @param id l'identifiant de la simulation a + * certain champs. + * + * @param id l'identifiant de la simulation a lire * @param control le control a mettre a jour en fonction de ce qui est lu * @param exclude les champs a exclure */ - static public void readControl(String id, SimulationControl control, String... exclude) { + public static void readControl(String id, SimulationControl control, String... exclude) { + File file = getSimulationControlFile(id); + readControl(file, control, exclude); + } + + /** + * Reli le fichier contenant les infos de SimulationControl, en excluant + * certain champs. + * + * @param controlFile le fichier de control + * @param control le control a mettre a jour en fonction de ce qui est lu + * @param exclude les champs a exclure + */ + public static void readControl(File controlFile, SimulationControl control, String... exclude) { try { Properties prop = new Properties(); - File file = getSimulationControlFile(id); - if (file.exists()) { - FileInputStream in = new FileInputStream(file); + if (controlFile.exists()) { + FileInputStream in = new FileInputStream(controlFile); try { prop.load(in); } finally { @@ -253,11 +266,11 @@ } else { if(log.isDebugEnabled()) { - log.debug("Control file '" + file.getAbsolutePath() + "'doesn't exists"); + log.debug("Control file '" + controlFile.getAbsolutePath() + "'doesn't exists"); } } - } catch (Exception eee) { - log.warn("Can't read control", eee); + } catch (Exception e) { + log.warn("Can't read control", e); } } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java 2008-12-22 15:59:12 UTC (rev 1719) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java 2008-12-23 11:24:23 UTC (rev 1720) @@ -122,8 +122,18 @@ return _("isisfish.simulator.launcher.inprocess"); } + /** + * Display message both in commons-logging and control text progress. + * + * @param control control + * @param message message to display + */ protected void message(SimulationControl control, String message) { - log.info(message); + // log + if(log.isInfoEnabled()) { + log.info(message); + } + // control if (control != null) { control.setText(message); } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SshSimulatorLauncher.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SshSimulatorLauncher.java 2008-12-22 15:59:12 UTC (rev 1719) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SshSimulatorLauncher.java 2008-12-23 11:24:23 UTC (rev 1720) @@ -26,10 +26,12 @@ import java.awt.Insets; import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.rmi.RemoteException; +import java.util.List; import javax.swing.JLabel; import javax.swing.JOptionPane; @@ -37,6 +39,7 @@ import javax.swing.JPasswordField; import javax.swing.JTextField; +import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -60,10 +63,9 @@ * simulation on that file. * * Isis-Fish must be installed on remote server. + * + * @see JSch * - * Scp code using jsch is taken from : - * http://www.jcraft.com/jsch/examples/ScpTo.java - * * @author chatellier * @version $Revision: 1.0 $ * @@ -75,195 +77,23 @@ /** Class logger */ protected static Log log = LogFactory.getLog(SshSimulatorLauncher.class); - protected class MyUserInfo implements UserInfo, UIKeyboardInteractive { - - protected String passphrase; - protected JTextField passphraseField = new JPasswordField(20); - protected String passwd; - protected JTextField passwordField = new JPasswordField(20); - - /** - * Constructor. - */ - public MyUserInfo() { - this(null); + /** + * Display message both in commons-logging and control text progress. + * + * @param control control + * @param message message to display + */ + protected void message(SimulationControl control, String message) { + // log + if (log.isInfoEnabled()) { + log.info(message); } - - /** - * Constructor with password. - * - * @param passwd password - */ - public MyUserInfo(String passwd) { - this.passwd = passwd; + // control + if (control != null) { + control.setText(message); } - - public boolean promptYesNo(String str) { - log.debug("promptYesNo"); - Object[] options = { "yes", "no" }; - int foo = JOptionPane.showOptionDialog(null, str, "Warning", - JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, - null, options, options[0]); - return foo == 0; - } - - public String getPassphrase() { - log.debug("getPassphrase"); - return passphrase; - } - - public boolean promptPassphrase(String message) { - log.debug("promptPassphrase"); - Object[] ob = { passphraseField }; - int result = JOptionPane.showConfirmDialog(null, ob, message, - JOptionPane.OK_CANCEL_OPTION); - boolean bResult = false; - if (result == JOptionPane.OK_OPTION) { - passphrase = passphraseField.getText(); - bResult = true; - } - return bResult; - } - - public String getPassword() { - log.debug("getPassword"); - return passwd; - } - - public boolean promptPassword(String message) { - log.debug("promptPassword"); - Object[] ob = { passwordField }; - int result = JOptionPane.showConfirmDialog(null, ob, message, - JOptionPane.OK_CANCEL_OPTION); - boolean bResult = false; - if (result == JOptionPane.OK_OPTION) { - passwd = passwordField.getText(); - bResult = true; - } - return bResult; - } - - public void showMessage(String message) { - JOptionPane.showMessageDialog(null, message); - } - - public String[] promptKeyboardInteractive(String destination, - String name, String instruction, String[] prompt, boolean[] echo) { - log.debug("promptKeyboardInteractive"); - final GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1, 1, - GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(0, 0, 0, 0), 0, 0); - Container panel = new JPanel(); - panel.setLayout(new GridBagLayout()); - - gbc.weightx = 1.0; - gbc.gridwidth = GridBagConstraints.REMAINDER; - gbc.gridx = 0; - panel.add(new JLabel(instruction), gbc); - gbc.gridy++; - - gbc.gridwidth = GridBagConstraints.RELATIVE; - - JTextField[] texts = new JTextField[prompt.length]; - for (int i = 0; i < prompt.length; i++) { - gbc.fill = GridBagConstraints.NONE; - gbc.gridx = 0; - gbc.weightx = 1; - panel.add(new JLabel(prompt[i]), gbc); - - gbc.gridx = 1; - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.weighty = 1; - if (echo[i]) { - texts[i] = new JTextField(20); - } else { - texts[i] = new JPasswordField(20); - } - panel.add(texts[i], gbc); - gbc.gridy++; - } - - String[] response = null; - if (JOptionPane.showConfirmDialog(null, panel, destination + ": " - + name, JOptionPane.OK_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION) { - response = new String[prompt.length]; - for (int i = 0; i < prompt.length; i++) { - response[i] = texts[i].getText(); - } - } - // else = cancel - return response; - } - } - - protected class NonInteractiveUserInfo implements UserInfo { - protected String passphrase; - protected JTextField passphraseField = new JPasswordField(20); - protected String passwd; - protected JTextField passwordField = new JPasswordField(20); - - /** - * Constructor with password. - * - * @param passwd password - */ - public NonInteractiveUserInfo(String passwd) { - this.passwd = passwd; - } - - public boolean promptYesNo(String str) { - log.debug("promptYesNo"); - Object[] options = { "yes", "no" }; - int foo = JOptionPane.showOptionDialog(null, str, "Warning", - JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, - null, options, options[0]); - return foo == 0; - } - - public String getPassphrase() { - log.debug("getPassphrase"); - return passphrase; - } - - public boolean promptPassphrase(String message) { - log.debug("promptPassphrase"); - Object[] ob = { passphraseField }; - int result = JOptionPane.showConfirmDialog(null, ob, message, - JOptionPane.OK_CANCEL_OPTION); - boolean bResult = false; - if (result == JOptionPane.OK_OPTION) { - passphrase = passphraseField.getText(); - bResult = true; - } - return bResult; - } - - public String getPassword() { - log.debug("getPassword"); - return passwd; - } - - public boolean promptPassword(String message) { - log.debug("promptPassword"); - Object[] ob = { passwordField }; - int result = JOptionPane.showConfirmDialog(null, ob, message, - JOptionPane.OK_CANCEL_OPTION); - boolean bResult = false; - if (result == JOptionPane.OK_OPTION) { - passwd = passwordField.getText(); - bResult = true; - } - return bResult; - } - - public void showMessage(String message) { - JOptionPane.showMessageDialog(null, message); - } - } - /* * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#maxSimulationThread() */ @@ -273,6 +103,14 @@ } /* + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return _("isisfish.simulator.launcher.remote"); + } + + /* * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#simulate(fr.ifremer.isisfish.simulator.launcher.SimulationService, fr.ifremer.isisfish.simulator.SimulationControl, java.io.File) */ @Override @@ -282,24 +120,32 @@ // start ssh session try { + + // connection + message(control, _("isisfish.simulation.remote.message.connection")); Session sshSession = openSSHSession(); - + // upload simulation on server + message(control, _("isisfish.simulation.remote.message.upload")); String remotePath = uploadSimulation(sshSession, simulationZip); // si l'upload a fonctionné - if(remotePath != null) { - launchSimulation(sshSession, simulationService, control, remotePath); + if (remotePath != null) { + message(control, _("isisfish.simulation.remote.message.launch")); + // just start a thread + checkSimulationProgression(sshSession, simulationService, + control); + launchSimulation(sshSession, simulationService, control, + remotePath); } } catch (JSchException e) { - if(log.isErrorEnabled()) { + if (log.isErrorEnabled()) { log.error(_("isisfish.error.simulation.remote.global")); } - throw new SimulationException("isisfish.error.simulation.remote.global", e); + throw new SimulationException( + _("isisfish.error.simulation.remote.global"), e); } - - - + return null; } @@ -314,53 +160,150 @@ JSch jsch = new JSch(); - // add ssh key - File sshKey = new File(IsisFish.config.getSimulatorSshPrivateKey()); - if(sshKey.canRead()) { - jsch.addIdentity(sshKey.getAbsolutePath()); - } - // extract connection infos String host = IsisFish.config.getSimulatorSshServer(); String username = IsisFish.config.getSimulatorSshUsername(); - String password = IsisFish.config.getSimulatorSshPassword(); + int port = 22; // by default, 22 - - if(host.indexOf(':') > 0) { + + if (host.indexOf(':') > 0) { String sPort = host.substring(host.indexOf(':') + 1); try { port = Integer.parseInt(sPort); - } - catch(NumberFormatException e) { - if(log.isWarnEnabled()) { - log.warn(_("isisfish.error.simulation.remote.wrongportvalue", sPort)); + } catch (NumberFormatException e) { + if (log.isWarnEnabled()) { + log.warn(_( + "isisfish.error.simulation.remote.wrongportvalue", + sPort)); } } host = host.substring(0, host.indexOf(':')); } - + + if (log.isInfoEnabled()) { + log.info(_("Try to log on %s@%s:%d", username, host, port)); + } + + // add ssh key + boolean sshKeyUsed = false; + File sshKey = IsisFish.config.getSSHPrivateKeyFilePath(); + if (sshKey.canRead()) { + if (log.isInfoEnabled()) { + log.info(_("Ssh key found '%s' will be used to connect to", + sshKey.getAbsoluteFile(), host)); + } + jsch.addIdentity(sshKey.getAbsolutePath()); + sshKeyUsed = true; + } + Session session = jsch.getSession(username, host, port); - + // username and password will be given via UserInfo interface. - UserInfo ui = new NonInteractiveUserInfo(password); + UserInfo ui = new SSHUserInfo(); session.setUserInfo(ui); session.connect(60000); // timeout - + + // test here, if password has been asked to user + if (session.isConnected() && sshKeyUsed && ui.getPassword() != null) { + putSshKeyOnRemoteServer(session, sshKey); + } return session; } /** * Close ssh session. * - * @param session + * @param session session to close */ protected void closeSSHSession(Session session) { - session.disconnect(); + if (session != null) { + session.disconnect(); + } } - + /** + * Add ssh key into $HOME/.ssh/authorized_keys file. + * + * Just connect and do an "echo xx >> + * @param session opened session + * @param sshKey + * @throws JSchException + */ + protected void putSshKeyOnRemoteServer(Session session, File sshKey) + throws JSchException { + + // get public key for argument private key file + // TODO always .pub ? + File publicKey = new File(sshKey.getAbsoluteFile() + ".pub"); + + // command to : + // - make ssh directory + // - add key to authorized_keys + String command = "if [ ! -d .ssh ] ; then mkdir .ssh; fi ; echo \"%s\" >> .ssh/authorized_keys"; + + try { + // use usefull readLines from commons-io + @SuppressWarnings("unchecked") + List<String> contents = FileUtils.readLines(publicKey); + + // only one line + if (contents != null && contents.size() == 1) { + command = String.format(command, contents.get(0)); + + if (log.isInfoEnabled()) { + log.info("Add key on remote authorized keys"); + } + if (log.isDebugEnabled()) { + log.debug("command is : " + command); + } + + // exec previous commande + Channel channel = session.openChannel("exec"); + ((ChannelExec) channel).setCommand(command); + + // read buffer + // seems to not work without it + InputStream in = channel.getInputStream(); + channel.connect(); + byte[] tmp = new byte[1024]; + while (true) { + while (in.available() > 0) { + int i = in.read(tmp, 0, 1024); + if (i < 0) + break; + if (log.isInfoEnabled()) { + log.info(new String(tmp, 0, i)); + } + } + if (channel.isClosed()) { + if (log.isInfoEnabled()) { + log.info("JSch channel exit-status: " + + channel.getExitStatus()); + } + break; + } + try { + Thread.sleep(1000); + } catch (Exception ee) { + } + } + channel.disconnect(); + // end read buffer + } + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error(_("Error while uploading public key to remote serveur authorized_keys"), + e); + } + } + } + + /** * Upload simulation file to server. * + * ScpTo code taken from : + * http://www.jcraft.com/jsch/examples/ScpTo.java + * * @param session already open valid ssh session * @param simulationFile simulation file to upload * @@ -373,7 +316,7 @@ // file info String filePath = simulationFile.getAbsolutePath(); - + FileInputStream fis = null; try { @@ -394,7 +337,7 @@ if (log.isDebugEnabled()) { log.debug("Uploading " + filePath); } - + // send "C0644 filesize filename", where filename should not include '/' long filesize = (new File(filePath)).length(); command = "C0644 " + filesize + " "; @@ -407,7 +350,7 @@ command += "\n"; out.write(command.getBytes()); out.flush(); - + if (checkAck(in) == 0) { // send a content of lfile @@ -438,22 +381,21 @@ } catch (JSchException e) { if (log.isErrorEnabled()) { log.error(_("isisfish.error.simulation.remote.upload", - filePath)); + filePath)); } } catch (IOException e) { if (log.isErrorEnabled()) { log.error(_("isisfish.error.simulation.remote.upload", - filePath)); + filePath)); } - } - finally { - try{ - if(fis!=null) { + } finally { + try { + if (fis != null) { fis.close(); } - }catch(IOException e) { - // exception ignoree - } + } catch (IOException e) { + // exception ignoree + } } return remotePath; @@ -462,6 +404,8 @@ /** * Check input stream validity. * + * Code taken from Jsch samples. + * * @param in input stream */ protected int checkAck(InputStream in) throws IOException { @@ -485,13 +429,17 @@ sb.append((char) c); } while (c != '\n'); if (b == 1) { // error - if(log.isErrorEnabled()) { - log.error(_("isisfish.error.simulation.remote.upload.stream",sb.toString())); + if (log.isErrorEnabled()) { + log.error(_( + "isisfish.error.simulation.remote.upload.stream", + sb.toString())); } } if (b == 2) { // fatal error - if(log.isFatalEnabled()) { - log.fatal(_("isisfish.error.simulation.remote.upload.stream",sb.toString())); + if (log.isFatalEnabled()) { + log.fatal(_( + "isisfish.error.simulation.remote.upload.stream", + sb.toString())); } } } @@ -502,23 +450,26 @@ * Launch simulation on remote server. * * @param session opened ssh session - * @param simulationService - * @param control - * @param remotePath + * @param simulationService simulation service + * @param control control + * @param remotePath remote zip simulation path * @throws JSchException */ - protected void launchSimulation(Session session, SimulationService simulationService, SimulationControl control, String remotePath) throws JSchException { - + protected void launchSimulation(Session session, + SimulationService simulationService, SimulationControl control, + String remotePath) throws JSchException { + String simulationId = control.getId(); - // remote launch command - String command = "java -jar isis-fish/isis-fish.jar"; - // no ui - command += " --option launch.ui false"; - // start simulation - command += " --simulateWithSimulation " + simulationId + " \"" + remotePath + "\""; - - if(log.isDebugEnabled()) { + String command = String.format("%s %s %s %s '%s' '%s' %s '%s' '%s'", + "java", // java command + "-jar", // java jar option + IsisFish.config.getSimulatorSshJarPath(), // remote jar path + "--option", "launch.ui", "false", // additionnal option ui + "--simulateWithSimulation", simulationId, remotePath // add option simulation + ); + + if (log.isDebugEnabled()) { log.debug("Launch : " + command); } @@ -529,7 +480,7 @@ try { InputStream in = channel.getInputStream(); - + channel.connect(); byte[] tmp = new byte[1024]; @@ -538,13 +489,14 @@ int i = in.read(tmp, 0, 1024); if (i < 0) break; - if(log.isInfoEnabled()) { + if (log.isInfoEnabled()) { log.info(new String(tmp, 0, i)); } } if (channel.isClosed()) { - if(log.isInfoEnabled()) { - log.info("exit-status: " + channel.getExitStatus()); + if (log.isInfoEnabled()) { + log.info("JSch channel exit-status: " + + channel.getExitStatus()); } break; } @@ -555,12 +507,377 @@ } channel.disconnect(); } catch (IOException e) { - throw new SimulationException(_("isisfish.error.simulation.remote.launch"), e); + throw new SimulationException( + _("isisfish.error.simulation.remote.launch"), e); } } + /** + * Launch a thread to check simulation progression on remote + * server. + * + * Use IsisFish.config.SIMULATOR_SSH_DATAPATH to download + * remote simulation control file. + * + * @param sshSession + * @param simulationService + * @param control + */ + protected void checkSimulationProgression(Session sshSession, + SimulationService simulationService, SimulationControl control) { + + Runnable controlRunnable = new RemoteSSHControlThread(sshSession, control); + Thread controlThread = new Thread(controlRunnable); + controlThread.start(); + + } + + /** + * Thread that check remote control file every 2s. + */ + protected class RemoteSSHControlThread implements Runnable { + + /** Sleep 2s */ + protected static final int SLEEPTIME = 2000; + + /** Opened ssh session */ + protected Session sshSession; + + /** Control (to update progression) */ + protected SimulationControl control; + + /** + * Constructor. + * @param sshSession + * + * @param control control + */ + protected RemoteSSHControlThread(Session sshSession, SimulationControl control) { + this.sshSession = sshSession; + this.control = control; + } + + /* + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + + boolean running = true; + while (running) { + + // wait + try { + Thread.sleep(SLEEPTIME); + + // download control file + File controlFile = downloadControlFile(control.getId()); + + if (controlFile != null) { + // on ne lit pas le stop, car le stop ne peut-etre appeler + // que par l'utilisateur qui est de ce cote de la machine + SimulationStorage.readControl(controlFile, control, + "stop"); + + // deleteTempFile + controlFile.delete(); + } + + } catch (InterruptedException e) { + if (log.isErrorEnabled()) { + log.error("Thread has been interrupted", e); + } + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error("Error while reading control file", e); + } + } + synchronized (control) { + running = control.isRunning(); + } + } + } + + /** + * Download remote simulation control file and store + * its content into temp file. + * + * ScpFrom code taken from : + * http://www.jcraft.com/jsch/examples/ScpFrom.java + * + * @return downloaded temp file (file have to be manualy deleted) + * @throws IOException + */ + protected File downloadControlFile(String simulationId) + throws IOException { + + File localFile = null; + + // build remote file path + // FIXME this path should be given by remote IsisFish app + // TODO to change + String remoteFile = IsisFish.config.getSimulatorSshDataPath(); + remoteFile += "/" + SimulationStorage.SIMULATION_PATH; + remoteFile += "/" + simulationId; + remoteFile += "/control"; + + // local tmp file + File tempFile = File.createTempFile(simulationId, "control"); + FileOutputStream fos=null; + + try { + // exec 'scp -f rfile' remotely + String command = "scp -f " + remoteFile; + Channel channel = sshSession.openChannel("exec"); + ((ChannelExec) channel).setCommand(command); + + // get I/O streams for remote scp + OutputStream out = channel.getOutputStream(); + InputStream in = channel.getInputStream(); + + channel.connect(); + + byte[] buf = new byte[1024]; + + // send '\0' + buf[0] = 0; + out.write(buf, 0, 1); + out.flush(); + + while (true) { + int c = checkAck(in); + if (c != 'C') { + break; + } + + // read '0644 ' + in.read(buf, 0, 5); + + long filesize = 0L; + while (true) { + if (in.read(buf, 0, 1) < 0) { + // error + break; + } + if (buf[0] == ' ') { + break; + } + filesize = filesize * 10L + (buf[0] - '0'); + } + + //String file = null; + for (int i = 0;; i++) { + in.read(buf, i, 1); + if (buf[i] == (byte) 0x0a) { + //file = new String(buf, 0, i); + break; + } + } + + // send '\0' + buf[0] = 0; + out.write(buf, 0, 1); + out.flush(); + + // read a content of lfile + fos = new FileOutputStream(localFile); + int foo; + while (true) { + if (buf.length < filesize) + foo = buf.length; + else + foo = (int) filesize; + foo = in.read(buf, 0, foo); + if (foo < 0) { + // error + break; + } + fos.write(buf, 0, foo); + filesize -= foo; + if (filesize == 0L) + break; + } + fos.close(); + fos = null; + + if (checkAck(in) != 0) { + localFile = tempFile; + } + + // send '\0' + buf[0] = 0; + out.write(buf, 0, 1); + out.flush(); + } + } + catch(IOException e){ + if(log.isErrorEnabled()) { + log.error("I/O error while downloading control file", e); + } + + } catch (JSchException e) { + if(log.isErrorEnabled()) { + log.error("Jsch error while downloading control file", e); + } + } + finally { + try{ + if(fos!=null) { + fos.close(); + } + } + catch(Exception ignored) { + } + } + + if(localFile == null) { + // an arror occurs + // so remove temp file + tempFile.delete(); + } + + return localFile; + } + } +} + +/** + * Class used to ask used for connection info. + * + * Password, passphrase... + */ +class SSHUserInfo implements UserInfo, UIKeyboardInteractive { + + /** + * Passphrase. + * + * Static to be stored on multiple connexion. + */ + protected static String passphrase; + + /** + * Passphrase text field. + */ + protected JTextField passphraseField = new JPasswordField(20); + + /** + * Password text field. + */ + protected String passwd; + + /** + * Password text field. + */ + protected JTextField passwordField = new JPasswordField(20); + + /** + * Call to ask user in remote server key + * can be trusted. Here, auto accept. + */ @Override - public String toString() { - return _("isisfish.simulator.launcher.remote"); + public boolean promptYesNo(String str) { + return true; } + + @Override + public String getPassphrase() { + return passphrase; + } + + @Override + public boolean promptPassphrase(String message) { + Object[] ob = { passphraseField }; + int result = JOptionPane.showConfirmDialog(null, ob, message, + JOptionPane.OK_CANCEL_OPTION); + boolean bResult = false; + if (result == JOptionPane.OK_OPTION) { + passphrase = passphraseField.getText(); + bResult = true; + } + return bResult; + } + + @Override + public String getPassword() { + return passwd; + } + + @Override + public boolean promptPassword(String message) { + Object[] ob = { passwordField }; + int result = JOptionPane.showConfirmDialog(null, ob, message, + JOptionPane.OK_CANCEL_OPTION); + boolean bResult = false; + if (result == JOptionPane.OK_OPTION) { + passwd = passwordField.getText(); + bResult = true; + } + return bResult; + } + + @Override + public void showMessage(String message) { + JOptionPane.showMessageDialog(null, message); + } + + @Override + public String[] promptKeyboardInteractive(String destination, String name, + String instruction, String[] prompt, boolean[] echo) { + final GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1, 1, + GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, + new Insets(0, 0, 0, 0), 0, 0); + Container panel = new JPanel(); + panel.setLayout(new GridBagLayout()); + + gbc.weightx = 1.0; + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.gridx = 0; + panel.add(new JLabel(instruction), gbc); + gbc.gridy++; + + gbc.gridwidth = GridBagConstraints.RELATIVE; + + JTextField[] texts = new JTextField[prompt.length]; + for (int i = 0; i < prompt.length; i++) { + gbc.fill = GridBagConstraints.NONE; + gbc.gridx = 0; + gbc.weightx = 1; + panel.add(new JLabel(prompt[i]), gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weighty = 1; + if (echo[i]) { + texts[i] = new JTextField(20); + } else { + texts[i] = new JPasswordField(20); + } + panel.add(texts[i], gbc); + gbc.gridy++; + } + + String[] response = null; + if (JOptionPane.showConfirmDialog(null, panel, destination + ": " + + name, JOptionPane.OK_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION) { + response = new String[prompt.length]; + for (int i = 0; i < prompt.length; i++) { + response[i] = texts[i].getText(); + + // hack to remember password + if (prompt[i] != null + && prompt[i].toLowerCase().indexOf("password") >= 0) { + passwd = response[i]; + } + + // hack to remember passphrase + if (prompt[i] != null + && prompt[i].toLowerCase().indexOf("passphrase") >= 0) { + passphrase = response[i]; + } + } + } + // else = cancel + return response; + } } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java 2008-12-22 15:59:12 UTC (rev 1719) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java 2008-12-23 11:24:23 UTC (rev 1720) @@ -21,7 +21,6 @@ import static org.codelutin.i18n.I18n._; -import java.beans.PropertyChangeListener; import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -37,7 +36,11 @@ import fr.ifremer.isisfish.simulator.SimulationControl; /** - * + * Lanceur de simulation dans un sous processus. + * + * @see ProcessBuilder + * @see Process + * * @author poussin * @version $Revision$ * Modified: isis-fish/trunk/src/main/resources/i18n/isis-fish-en_GB.properties =================================================================== --- isis-fish/trunk/src/main/resources/i18n/isis-fish-en_GB.properties 2008-12-22 15:59:12 UTC (rev 1719) +++ isis-fish/trunk/src/main/resources/i18n/isis-fish-en_GB.properties 2008-12-23 11:24:23 UTC (rev 1720) @@ -21,6 +21,7 @@ Clear\ done\ jobs= Could\ not\ found\ formule\ type\ %s\ autorised\ type\ are\ %s= Error\ during\ vcs\ initialisation= +Error\ while\ uploading\ public\ key\ to\ remote\ serveur\ authorized_keys= Generate\ next\ simulation= Import\ one\ java\ file\ script\ source= Import\ simulation\ file\ %s\ in\ directory\ %s\ and\ rename\ from\ %s\ to\ %s= @@ -34,7 +35,6 @@ Local\ repository\ exists\ but\ it's\ not\ valide\ for\ current\ vcs\:\ %s= Master\ plan= Month\ Gap\ BetweenRepro\ Recruitment= -No\ database\ version\ %s\ found\ and\ can't\ get\ it.\\n= Normal\ stop\ thread,\ this\ is\ not\ an\ error= Not\ start\ simulation\ %s\ because\ user\ ask\ stop= Region\ %s\ allready\ exist\ in\ repository.\ Can't\ import= @@ -42,14 +42,15 @@ Rename\ data\ directory\ to\ %s= Show\ help= SimulationExecutor\ started\ with\ %s\ thread\ for\ %s= +Ssh\ key\ found\ '%s'\ will\ be\ used\ to\ connect\ to= Stop\ simulation\ plan,\ because\ can't\ call\ afterSimulation\ correctly\ on\ plan\ %s= Stop\ the\ process= SubProcess\ start\:\ %s\ %s= Switch\ repository\ type\ to\ none= The\ equation\ used\ is\ the\ population's\ growth\ curve,\ it\ needs\ to\ be\ defined\ first.= +Try\ to\ log\ on\ %s@%s\:%d= Use\ branches,\ switch\ not\ needed= User\ stop\ simulation\ %s= -Your\ database\ repository\:\ %s\\n\ don't\ use\ correct= cant\ start\ nimbus= could\ not\ close\ reader\ %1$s=could not close reader %1$s could\ not\ create\ simulation\ filter\ model\ for\ reason\ %1$s=could not create simulation filter model for reason %1$s @@ -63,7 +64,7 @@ destination\ already\ exists\ %s\ use\ \\'force\\'\ argument\ to\ force\ overwrite= directory\ %s\ must\ be\ a\ directory= filter\ loaded\ in\ %1$s\ ms\ \:\ found\ %2$s\ lines.=filter loaded in %1$s ms \: found %2$s lines. -isisfish.about.abouthtmltext=<html><b>Isis-Fish (%s)</b><br /><br />Copyright 2002 - 2008, Ifremer - Code Lutin.<br /><br /><a href\="http\://isis-fish.labs.libre-entreprise.org">http\://isis-fish.labs.libre-entreprise.org</a><br /><br />Please, report any bug you can found.<html> +isisfish.about.abouthtmltext=<html><b>Isis-Fish (%s)</b><br /><br />Copyright IFREMER-MAERHA 2000-2008.<br /><br /><a href\="http\://isis-fish.labs.libre-entreprise.org">http\://isis-fish.labs.libre-entreprise.org</a><br /><br />Please, report any bug you can found.<html> isisfish.about.licensetext=You can modify and redistribute the program under the conditions of the GNU General Public License (version 2 or later). A copy of the GPL is in the file "LICENSE.txt" provided with Isis-Fish. All rights reserved. No guarantees are provided for use of this program. isisfish.about.title=About Isis-Fish... isisfish.advancedParameters.title=advanced Parameters @@ -82,10 +83,10 @@ isisfish.change.equation=Can't change equation isisfish.commit.message=Enter commit message isisfish.common.add=add -isisfish.common.add.short=add short +isisfish.common.add.short=add isisfish.common.alert=alert isisfish.common.apply=apply -isisfish.common.blank= +isisfish.common.blank=\ isisfish.common.cancel=cancel isisfish.common.check=check isisfish.common.clear=clear @@ -148,11 +149,11 @@ isisfish.config.main.password.description= isisfish.config.main.projectName.description=name of project isisfish.config.main.regionMap.description= -isisfish.config.main.remoteSimulator.description= +isisfish.config.main.remoteCaparmor.description= isisfish.config.main.resultExport.description= +isisfish.config.main.simulation.ssh.datapath.description= +isisfish.config.main.simulation.ssh.jarpath.description= isisfish.config.main.simulation.ssh.login.description= -isisfish.config.main.simulation.ssh.password.description= -isisfish.config.main.simulation.ssh.privatekey.description= isisfish.config.main.simulation.ssh.server.description= isisfish.config.main.simulationServer.description= isisfish.config.main.simulationShowOnlyError.description= @@ -559,7 +560,7 @@ isisfish.message.remove.unnecessary.cells= isisfish.message.removing.region=Removing region %1$s ... isisfish.message.result.verif.region=R\u00E9sultat de la v\u00E9rification de la r\u00E9gion -isisfish.message.save.finished=save finished +isisfish.message.save.finished=Save finished isisfish.message.saveModel.finished=Save model finished isisfish.message.setting.cache.aspects=Setting Cache aspects isisfish.message.setting.trace.aspects=Setting Trace aspects @@ -833,9 +834,9 @@ isisfish.sensibilityWizard.title=Sensibility Wizard isisfish.server.ssh.generateKey.title=Generate Ssh key isisfish.setOfVessels.comments=Comments -isisfish.setOfVessels.fixedCosts=fixedCosts -isisfish.setOfVessels.name=name -isisfish.setOfVessels.numberOfVessels=numberOfVessels +isisfish.setOfVessels.fixedCosts=Fixed costs +isisfish.setOfVessels.name=Name +isisfish.setOfVessels.numberOfVessels=Number of vessels isisfish.setOfVessels.technicalEfficiency= isisfish.setOfVessels.title=Caracteristics isisfish.setOfVessels.vesselType=vesselType @@ -850,25 +851,28 @@ isisfish.simulation.menu.save=Save simulation isisfish.simulation.menu.simulation=Simulation isisfish.simulation.name=Simulation name +isisfish.simulation.remote.message.connection=Connecting to Caparmor +isisfish.simulation.remote.message.launch=Launching simulation +isisfish.simulation.remote.message.upload=Uploading simulation isisfish.simulation.title=Simulation launcher isisfish.simulator.launcher.inprocess=in current process -isisfish.simulator.launcher.remote=on remote server +isisfish.simulator.launcher.remote=on Caparmor server isisfish.simulator.launcher.subprocess=in subprocess isisfish.simulator.simulaction.badid=Can't start simulation, bad id\: %s isisfish.simulator.subprocess.readoutput.error= -isisfish.species.age=age +isisfish.species.age=Age isisfish.species.cee=CEE isisfish.species.comments=Comments -isisfish.species.length=length +isisfish.species.length=Length isisfish.species.name=Species name isisfish.species.rubbinCode=Rubbin code isisfish.species.scientificName=Scientific name -isisfish.species.structured=structured +isisfish.species.structured=Structured isisfish.strategy.comments=Comments -isisfish.strategy.inactivity= -isisfish.strategy.inactivityEquationUsed= -isisfish.strategy.name=name -isisfish.strategy.proportionSetOfVessels=proportionSetOfVessels +isisfish.strategy.inactivity=Inactivity equation +isisfish.strategy.inactivityEquationUsed=Use inactivity equation +isisfish.strategy.name=Name +isisfish.strategy.proportionSetOfVessels=Set of vessels proportion isisfish.strategy.title=Caracteristics isisfish.strategyMonthInfo.metier=Metier isisfish.strategyMonthInfo.minInactivityDays=minInactivityDays Modified: isis-fish/trunk/src/main/resources/i18n/isis-fish-fr_FR.properties =================================================================== --- isis-fish/trunk/src/main/resources/i18n/isis-fish-fr_FR.properties 2008-12-22 15:59:12 UTC (rev 1719) +++ isis-fish/trunk/src/main/resources/i18n/isis-fish-fr_FR.properties 2008-12-23 11:24:23 UTC (rev 1720) @@ -21,6 +21,7 @@ Clear\ done\ jobs= Could\ not\ found\ formule\ type\ %s\ autorised\ type\ are\ %s= Error\ during\ vcs\ initialisation= +Error\ while\ uploading\ public\ key\ to\ remote\ serveur\ authorized_keys= Generate\ next\ simulation= Import\ one\ java\ file\ script\ source= Import\ simulation\ file\ %s\ in\ directory\ %s\ and\ rename\ from\ %s\ to\ %s= @@ -34,7 +35,6 @@ Local\ repository\ exists\ but\ it's\ not\ valide\ for\ current\ vcs\:\ %s= Master\ plan= Month\ Gap\ BetweenRepro\ Recruitment= -No\ database\ version\ %s\ found\ and\ can't\ get\ it.\\n= Normal\ stop\ thread,\ this\ is\ not\ an\ error= Not\ start\ simulation\ %s\ because\ user\ ask\ stop= Region\ %s\ allready\ exist\ in\ repository.\ Can't\ import= @@ -42,14 +42,15 @@ Rename\ data\ directory\ to\ %s= Show\ help= SimulationExecutor\ started\ with\ %s\ thread\ for\ %s= +Ssh\ key\ found\ '%s'\ will\ be\ used\ to\ connect\ to= Stop\ simulation\ plan,\ because\ can't\ call\ afterSimulation\ correctly\ on\ plan\ %s= Stop\ the\ process= SubProcess\ start\:\ %s\ %s= Switch\ repository\ type\ to\ none= The\ equation\ used\ is\ the\ population's\ growth\ curve,\ it\ needs\ to\ be\ defined\ first.= +Try\ to\ log\ on\ %s@%s\:%d= Use\ branches,\ switch\ not\ needed= User\ stop\ simulation\ %s= -Your\ database\ repository\:\ %s\\n\ don't\ use\ correct= cant\ start\ nimbus= could\ not\ close\ reader\ %1$s=could not close reader %1$s could\ not\ create\ simulation\ filter\ model\ for\ reason\ %1$s=could not create simulation filter model for reason %1$s @@ -63,7 +64,7 @@ destination\ already\ exists\ %s\ use\ \\'force\\'\ argument\ to\ force\ overwrite= directory\ %s\ must\ be\ a\ directory= filter\ loaded\ in\ %1$s\ ms\ \:\ found\ %2$s\ lines.=filter loaded in %1$s ms \: found %2$s lines. -isisfish.about.abouthtmltext=<html><b>Isis-Fish (%s)</b><br /><br />Copyright 2002 - 2008, Ifremer - Code Lutin.<br /><br /><a href\="http\://isis-fish.labs.libre-entreprise.org">http\://isis-fish.labs.libre-entreprise.org</a><br /><br />Merci de rapporter les bugs.<html> +isisfish.about.abouthtmltext=<html><b>Isis-Fish (%s)</b><br /><br />Copyright IFREMER-MAERHA 2000-2008.<br /><br /><a href\="http\://isis-fish.labs.libre-entreprise.org">http\://isis-fish.labs.libre-entreprise.org</a><br /><br />Merci de rapporter les bugs.<html> isisfish.about.licensetext=Vous pouvez modifier et redistribuer ce programme sous les conditions \u00E9nonc\u00E9es par la licence GNU GPL (version 2 ou ult\u00E9rieure). Une copie de la licence GPL est dans le fichier \u00AB\u00A0LICENSE.txt\u00A0\u00BB fourni avec Isis-Fish. Tous droits r\u00E9serv\u00E9s. Aucune garantie n'est fournie pour l'utilisation de ce programme. isisfish.about.title=\u00C0 propos de Isis-Fish... isisfish.advancedParameters.title=Param\u00E8tres avanc\u00E9s @@ -82,10 +83,10 @@ isisfish.change.equation=Ne peut pas changer l'\u00E9quation isisfish.commit.message=Entrer un message de commit isisfish.common.add=Ajouter -isisfish.common.add.short=isisfish.common.add.short +isisfish.common.add.short=Aj. isisfish.common.alert=alerte isisfish.common.apply=Appliquer -isisfish.common.blank= +isisfish.common.blank=\ isisfish.common.cancel=Annuler isisfish.common.check=V\u00E9rifier isisfish.common.clear=Effacer @@ -148,11 +149,11 @@ isisfish.config.main.password.description=le mot de passe pour se connecter au serveur de simulations distant isisfish.config.main.projectName.description=le nom du projet isisfish.config.main.regionMap.description=le nom du r\u00E9pertoire contenant les maps d'une r\u00E9gion -isisfish.config.main.remoteSimulator.description=lance les simulations sur un serveur distant +isisfish.config.main.remoteCaparmor.description=lance les simulations sur un serveur distant isisfish.config.main.resultExport.description=TODO +isisfish.config.main.simulation.ssh.datapath.description= +isisfish.config.main.simulation.ssh.jarpath.description= isisfish.config.main.simulation.ssh.login.description= -isisfish.config.main.simulation.ssh.password.description= -isisfish.config.main.simulation.ssh.privatekey.description= isisfish.config.main.simulation.ssh.server.description= isisfish.config.main.simulationServer.description=l'url du serveur de simulations distant isisfish.config.main.simulationShowOnlyError.description=pour indiquer si l'on doit conserver dans l'UI des simulations termin\u00E9es uniquement celles avec erreur @@ -559,7 +560,7 @@ isisfish.message.remove.unnecessary.cells= isisfish.message.removing.region=Suppression de lar\u00E9gion %1$s ... isisfish.message.result.verif.region=R\u00E9sultat de la v\u00E9rification de la r\u00E9gion -isisfish.message.save.finished=sauvegarde termin\u00E9e +isisfish.message.save.finished=Sauvegarde termin\u00E9e isisfish.message.saveModel.finished=Sauvegarde du mod\u00E8le termin\u00E9e isisfish.message.setting.cache.aspects=Mise en place des aspects Cache isisfish.message.setting.trace.aspects=Mise en place des aspects Trace @@ -708,7 +709,7 @@ isisfish.queue.stopSimulation=Arr\u00EAter la simulation isisfish.queue.title=Queue isisfish.result.abundance=Abondance -isisfish.result.add=Ajouter un r\u00E9sultat\= +isisfish.result.add=Ajouter un r\u00E9sultat isisfish.result.begin.simulation=En d\u00E9but de simulation\: isisfish.result.capture=Capturer isisfish.result.capture.metier=Capturer par m\u00E9tier @@ -831,10 +832,10 @@ isisfish.sensWizardPanels.validate=Valider isisfish.sensWizardPanels.values=Valeurs isisfish.sensibilityWizard.title=Sensibility Wizard -isisfish.server.ssh.generateKey.title=isisfish.server.ssh.generateKey.title +isisfish.server.ssh.generateKey.title=G\u00E9n\u00E9rer une cl\u00E9 SSH isisfish.setOfVessels.comments=Commentaires isisfish.setOfVessels.fixedCosts=Co\u00FBts fixes -isisfish.setOfVessels.name=nom +isisfish.setOfVessels.name=Nom isisfish.setOfVessels.numberOfVessels=Nombre de navires isisfish.setOfVessels.technicalEfficiency= isisfish.setOfVessels.title=Caract\u00E9ristiques @@ -850,24 +851,27 @@ isisfish.simulation.menu.save=Sauver la simulation isisfish.simulation.menu.simulation=Simulation isisfish.simulation.name=Nom de la simulation +isisfish.simulation.remote.message.connection=Connexion \u00E0 Caparmor +isisfish.simulation.remote.message.launch=Lancement de la simulation +isisfish.simulation.remote.message.upload=Upload de la simulation isisfish.simulation.title=Lanceur de simulation isisfish.simulator.launcher.inprocess=dans le m\u00EAme processus -isisfish.simulator.launcher.remote=sur un serveur distant +isisfish.simulator.launcher.remote=sur le serveur Caparmor isisfish.simulator.launcher.subprocess=dans un sous processus isisfish.simulator.simulaction.badid=Impossible de lancer la simulation '%s' \: l'identifiant existe d\u00E9j\u00E0 \! isisfish.simulator.subprocess.readoutput.error= -isisfish.species.age=age +isisfish.species.age=Age isisfish.species.cee=CEE isisfish.species.comments=Commentaires -isisfish.species.length=longueur +isisfish.species.length=Longueur isisfish.species.name=Nom des esp\u00E8ces isisfish.species.rubbinCode=Code Rubbin isisfish.species.scientificName=Scientific name isisfish.species.structured=Structur\u00E9 isisfish.strategy.comments=Commentaires -isisfish.strategy.inactivity= -isisfish.strategy.inactivityEquationUsed= -isisfish.strategy.name=nom +isisfish.strategy.inactivity=\u00C9quation d'inactivit\u00E9 +isisfish.strategy.inactivityEquationUsed=Utiliser une \u00E9quation d'inactivit\u00E9 +isisfish.strategy.name=Nom isisfish.strategy.proportionSetOfVessels=Proportion des ensembles de navires isisfish.strategy.title=Caract\u00E9ristiques isisfish.strategyMonthInfo.metier=M\u00E9tier