From: <st...@us...> - 2010-01-04 16:47:37
|
Revision: 8118 http://smartfrog.svn.sourceforge.net/smartfrog/?rev=8118&view=rev Author: steve_l Date: 2010-01-04 16:47:27 +0000 (Mon, 04 Jan 2010) Log Message: ----------- SFOS-1374 Have Mombasa push out SF descriptors to dynamically allocated machines Modified Paths: -------------- trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/common/AbstractClusterFarmer.java trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/deployment/NodeDeploymentOverSSHFactory.java Added Paths: ----------- trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/deployment/NodeDeploymentOverSSH.java Modified: trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/common/AbstractClusterFarmer.java =================================================================== --- trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/common/AbstractClusterFarmer.java 2009-12-24 13:33:13 UTC (rev 8117) +++ trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/common/AbstractClusterFarmer.java 2010-01-04 16:47:27 UTC (rev 8118) @@ -75,7 +75,14 @@ @Override public synchronized void sfStart() throws SmartFrogException, RemoteException { super.sfStart(); - deploymentFactory = (NodeDeploymentServiceFactory) sfResolve(ATTR_DEPLOYMENT_FACTORY, deploymentFactory, true); + Prim p = sfResolve(ATTR_DEPLOYMENT_FACTORY, (Prim)null, true); + if (!(p instanceof NodeDeploymentServiceFactory)) { + throw new SmartFrogResolutionException(new Reference(ATTR_DEPLOYMENT_FACTORY), + sfCompleteName(), + "Deployment factory is "+p.getClass()+" and not an instance of NodeDeploymentServiceFactory", + p); + } + deploymentFactory = (NodeDeploymentServiceFactory) p; resolveClusterLimit(); } Added: trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/deployment/NodeDeploymentOverSSH.java =================================================================== --- trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/deployment/NodeDeploymentOverSSH.java (rev 0) +++ trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/deployment/NodeDeploymentOverSSH.java 2010-01-04 16:47:27 UTC (rev 8118) @@ -0,0 +1,230 @@ +/* (C) Copyright 2009 Hewlett-Packard Development Company, LP + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +For more information: www.smartfrog.org + +*/ +package org.smartfrog.services.cloudfarmer.server.deployment; + +import org.smartfrog.services.cloudfarmer.api.NodeDeploymentService; +import org.smartfrog.services.cloudfarmer.api.ClusterNode; +import org.smartfrog.services.ports.PortUtils; +import org.smartfrog.services.ssh.ScpTo; +import org.smartfrog.services.ssh.SshCommand; +import org.smartfrog.sfcore.common.SmartFrogException; +import org.smartfrog.sfcore.componentdescription.ComponentDescription; +import org.smartfrog.sfcore.utils.SFExpandFully; +import org.smartfrog.sfcore.logging.OutputStreamLog; +import org.apache.tools.ant.util.TeeOutputStream; +import com.jcraft.jsch.Session; +import com.jcraft.jsch.JSchException; + +import java.io.IOException; +import java.io.File; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; + +/** + * SSH based deployment, assumes deploy-by-copy to a specified destdir, uses a given login + * <p/> + * This is an inner + * class and it uses the parent to do the work + */ +final class NodeDeploymentOverSSH extends AbstractNodeDeployment implements NodeDeploymentService { + + private String hostname; + private static final String SF_SUFFIX = ".sf"; + private static final String SSH_RESPONSE_CHARSET = "ISO-8859-1"; + private NodeDeploymentOverSSHFactory factory; + + NodeDeploymentOverSSH(NodeDeploymentOverSSHFactory factory, ClusterNode node) { + super(node); + this.factory = factory; + hostname = node.getExternalHostname(); + } + + /** + * This is here to stop any code even accidentally asking the superclass for a session + * @return nothing + * @throws IllegalStateException always + */ + private Session getSession() { + throw new IllegalStateException("getSession not supported"); + } + + private String makeSFCommand(String command) { + return factory.makeSFCommand(command); + } + + /** + * {@inheritDoc} + * @param name application name + * @param cd component description + * @throws IOException IO problems + * @throws SmartFrogException SF problems + */ + @Override + public synchronized void deployApplication(String name, ComponentDescription cd) + throws IOException, SmartFrogException { + if(!getClusterNode().isExternallyVisible()) { + factory.sfLog().warn("This node is not externally visible. Unless we are in the cell, deployment will not work"); + } + File localtempfile = File.createTempFile(factory.getTempfilePrefix(), SF_SUFFIX); + String desttempfile = factory.getDestDir() + factory.getTempfilePrefix() + getNextNumber() + SF_SUFFIX; + SFExpandFully.saveCDtoFile(cd, localtempfile); + ArrayList<File> sourceFiles = new ArrayList<File>(); + ArrayList<String> destFiles = new ArrayList<String>(); + sourceFiles.add(localtempfile); + destFiles.add(desttempfile); + String connectionDetails = getConnectionDetails(); + factory.getLog().info("Deploying application "+ name + " to " + connectionDetails); + + //make a pre-emptive connection to the port; this blocks waiting for things like machines to come up + + PortUtils.checkPort(hostname, factory.getPort(), factory.getPortConnectTimeout()); + + + Session session = null; + try { + session = factory.demandCreateSession(hostname); + ArrayList<String> commandsList = new ArrayList<String>(1); + commandsList.add("mkdir -p " + factory.getDestDir()); + commandsList.add("exit"); + sshExec(session, commandsList, true); + + ScpTo scp = new ScpTo(factory.sfLog()); + //copy up the temp files + factory.getLog().info("copying " + localtempfile + " to " + desttempfile); + scp.doCopy(session, destFiles, sourceFiles); + String sshCommand; + sshCommand = makeSFCommand("sfStart") + " " + "localhost" + " " + name + " " + desttempfile; + factory.getLog().info("executing: " + sshCommand); + commandsList = new ArrayList<String>(1); + commandsList.add(sshCommand); + if (!factory.isKeepFiles()) { + commandsList.add("rm " + desttempfile); + } + commandsList.add("exit"); + sshExec(session, commandsList, true); + } catch (JSchException e) { + factory.getLog().error("Failed to upload to " + connectionDetails + " : " + e, e); + throw factory.forward(e, connectionDetails); + } finally { + endSession(session); + if(!factory.isKeepFiles()) { + localtempfile.delete(); + } + } + } + + private String getConnectionDetails() { + return factory.getUserName() +"@" +hostname + ":" + factory.getPort() ; + } + + /** + * Get a new number + * @return a new number for use in filenames + */ + private synchronized int getNextNumber() { + return factory.getNextNumber(); + } + + private void sshExec(Session session, String commandString, boolean checkResponse) + throws JSchException, IOException, SmartFrogException { + ArrayList<String> commandsList = new ArrayList<String>(1); + commandsList.add(commandString); + sshExec(session, commandsList, checkResponse); + } + + private int sshExec(Session session, ArrayList<String> commandsList, boolean checkResponse) + throws JSchException, IOException, SmartFrogException { + SshCommand command = new SshCommand(factory.sfLog(), null); + OutputStreamLog outputStreamLog = new OutputStreamLog(factory.getLog(), factory.getOutputLogLevel()); + ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); + TeeOutputStream teeOut = new TeeOutputStream(outputStreamLog, byteOutputStream); + int exitCode = command.execute(session, commandsList, teeOut, factory.getTimeout()); + if (checkResponse && exitCode != 0) { + String output = byteOutputStream.toString(SSH_RESPONSE_CHARSET); + throw new SmartFrogException("Error response on command " + commandsList.get(0) + +":-\n" + + output); + } + return exitCode; + } + + /** + * End a session + * + * @param session session, can be null + */ + private void endSession(Session session) { + if (session != null && session.isConnected()) { + session.disconnect(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean terminateApplication(String name, boolean normal, String exitText) + throws IOException, SmartFrogException { + Session session = null; + try { + factory.getLog().info("Terminating application " + name + " for " + exitText); + session = factory.demandCreateSession(hostname); + ArrayList<String> commandsList = new ArrayList<String>(1); + String sshCommand = makeSFCommand("sfTerminate") + " " + "localhost" + " " + name; + factory.getLog().info("executing: " + sshCommand); + commandsList.add(sshCommand); + commandsList.add("exit"); + return sshExec(session, commandsList, false) == 0; + } catch (JSchException e) { + String connectionDetails = getConnectionDetails(); + factory.getLog().error("Failed to terminate "+ name+ " on " + connectionDetails + " : " + e, e); + throw factory.forward(e, connectionDetails); + } finally { + endSession(session); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void pingApplication(String name) throws IOException, SmartFrogException { + } + + /** + * {@inheritDoc} + */ + @Override + public String getServiceDescription() throws IOException, SmartFrogException { + return "SSH to " + hostname; + } + + @Override + public String getApplicationDescription(String name) throws IOException, SmartFrogException { + return ""; + } + + /** + * {@inheritDoc} + */ + @Override + public void terminate() throws IOException, SmartFrogException { + } +} Modified: trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/deployment/NodeDeploymentOverSSHFactory.java =================================================================== --- trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/deployment/NodeDeploymentOverSSHFactory.java 2009-12-24 13:33:13 UTC (rev 8117) +++ trunk/core/components/cloudfarmer/src/org/smartfrog/services/cloudfarmer/server/deployment/NodeDeploymentOverSSHFactory.java 2010-01-04 16:47:27 UTC (rev 8118) @@ -8,20 +8,14 @@ import org.smartfrog.services.cloudfarmer.api.NodeDeploymentServiceFactory; import org.smartfrog.services.ssh.AbstractSSHComponent; import org.smartfrog.services.ssh.SSHComponent; -import org.smartfrog.services.ssh.ScpTo; -import org.smartfrog.services.ssh.SshCommand; -import org.smartfrog.services.ports.PortUtils; import org.smartfrog.sfcore.common.SmartFrogException; -import org.smartfrog.sfcore.componentdescription.ComponentDescription; +import org.smartfrog.sfcore.common.SmartFrogLifecycleException; import org.smartfrog.sfcore.logging.LogLevel; -import org.smartfrog.sfcore.logging.OutputStreamLog; -import org.smartfrog.sfcore.utils.SFExpandFully; -import org.apache.tools.ant.util.TeeOutputStream; -import java.io.File; +import org.smartfrog.sfcore.logging.Log; +import org.smartfrog.sfcore.logging.LogSF; + import java.io.IOException; -import java.io.ByteArrayOutputStream; import java.rmi.RemoteException; -import java.util.ArrayList; import java.util.Random; /** @@ -50,8 +44,57 @@ public NodeDeploymentOverSSHFactory() throws RemoteException { } + + public String getDestDir() { + return destDir; + } + public JSch getJschInstance() { + return jschInstance; + } + + public String getSfHomeDir() { + return sfHomeDir; + } + + public boolean isKeepFiles() { + return keepFiles; + } + + public int getPortConnectTimeout() { + return portConnectTimeout; + } + + public String getTempfilePrefix() { + return tempfilePrefix; + } + + public int getOutputLogLevel() { + return outputLogLevel; + } + + public LogSF getLog() { + return log; + } + /** + * Get a new number + * + * @return a new number for use in filenames + */ + public synchronized int getNextNumber() { + return random.nextInt(); + } + + /** + * {@inheritDoc} + * + */ + public SmartFrogLifecycleException forward(Throwable thrown, String connectionDetails) { + return super.forward(thrown, connectionDetails); + } + + /** * At startup, the jsch instance is created * * @throws SmartFrogException problems -can include a nested JSchException @@ -92,7 +135,7 @@ */ @Override public NodeDeploymentService createInstance(ClusterNode node) throws IOException, SmartFrogException { - return new NodeDeploymentOverSSH(node); + return new NodeDeploymentOverSSH(this, node); } @@ -110,197 +153,17 @@ return newSession; } - /** - * SSH based deployment, assumes deploy-by-copy to a specified destdir, uses a given login - * <p/> - * This is an inner - * class and it uses the parent to do the work + * Create an SF command resolved to the target SF home directory + * @param command the command to be run + * @return the command to run at the far end */ - final class NodeDeploymentOverSSH extends AbstractNodeDeployment implements NodeDeploymentService { - - private String hostname; - private static final String SF_SUFFIX = ".sf"; - private static final String SSH_RESPONSE_CHARSET = "ISO-8859-1"; - - NodeDeploymentOverSSH(ClusterNode node) { - super(node); - hostname = node.getExternalHostname(); + public String makeSFCommand(String command) { + if (getSfHomeDir().isEmpty()) { + return command; + } else { + return getSfHomeDir() + command; } - - /** - * This is here to stop any code even accidentally asking the superclass for a session - * @return nothing - * @throws IllegalStateException always - */ - private Session getSession() { - throw new IllegalStateException("getSession not supported"); - } - - private String makeSFCommand(String command) { - if(sfHomeDir.isEmpty()) { - return command; - } - return sfHomeDir + command; - } - /** - * {@inheritDoc} - * @param name application name - * @param cd component description - * @throws IOException IO problems - * @throws SmartFrogException SF problems - */ - @Override - public synchronized void deployApplication(String name, ComponentDescription cd) - throws IOException, SmartFrogException { - if(!getClusterNode().isExternallyVisible()) { - sfLog().warn("This node is not externally visible. Unless we are in the cell, deployment will not work"); - } - File localtempfile = File.createTempFile(tempfilePrefix, SF_SUFFIX); - String desttempfile = destDir + tempfilePrefix + getNextNumber() + SF_SUFFIX; - SFExpandFully.saveCDtoFile(cd, localtempfile); - ArrayList<File> sourceFiles = new ArrayList<File>(); - ArrayList<String> destFiles = new ArrayList<String>(); - sourceFiles.add(localtempfile); - destFiles.add(desttempfile); - String connectionDetails = getConnectionDetails(); - log.info("Deploying application "+ name + " to " + connectionDetails); - - //make a pre-emptive connection to the port; this blocks waiting for things like machines to come up - - PortUtils.checkPort(hostname, getPort(), portConnectTimeout); - - - Session session = null; - try { - session = demandCreateSession(hostname); - ArrayList<String> commandsList = new ArrayList<String>(1); - commandsList.add("mkdir -p " + destDir); - commandsList.add("exit"); - sshExec(session, commandsList, true); - - ScpTo scp = new ScpTo(sfLog()); - //copy up the temp files - log.info("copying " + localtempfile + " to " + desttempfile); - scp.doCopy(session, destFiles, sourceFiles); - String sshCommand; - sshCommand = makeSFCommand("sfStart") + " " + "localhost" + " " + name + " " + desttempfile; - log.info("executing: " + sshCommand); - commandsList = new ArrayList<String>(1); - commandsList.add(sshCommand); - if (!keepFiles) { - commandsList.add("rm " + desttempfile); - } - commandsList.add("exit"); - sshExec(session, commandsList, true); - } catch (JSchException e) { - log.error("Failed to upload to " + connectionDetails + " : " + e, e); - throw forward(e, connectionDetails); - } finally { - endSession(session); - if(!keepFiles) { - localtempfile.delete(); - } - } - } - - private String getConnectionDetails() { - return getUserName() +"@" +hostname + ":" + getPort() ; - } - - /** - * Get a new number - * @return a new number for use in filenames - */ - private synchronized int getNextNumber() { - return random.nextInt(); - } - - private void sshExec(Session session, String commandString, boolean checkResponse) - throws JSchException, IOException, SmartFrogException { - ArrayList<String> commandsList = new ArrayList<String>(1); - commandsList.add(commandString); - sshExec(session, commandsList, checkResponse); - } - - private int sshExec(Session session, ArrayList<String> commandsList, boolean checkResponse) - throws JSchException, IOException, SmartFrogException { - SshCommand command = new SshCommand(sfLog(), null); - OutputStreamLog outputStreamLog = new OutputStreamLog(log, outputLogLevel); - ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); - TeeOutputStream teeOut = new TeeOutputStream(outputStreamLog, byteOutputStream); - int exitCode = command.execute(session, commandsList, teeOut, getTimeout()); - if (checkResponse && exitCode != 0) { - String output = byteOutputStream.toString(SSH_RESPONSE_CHARSET); - throw new SmartFrogException("Error response on command " + commandsList.get(0) - +":-\n" - + output); - } - return exitCode; - } - - /** - * End a session - * - * @param session session, can be null - */ - private void endSession(Session session) { - if (session != null && session.isConnected()) { - session.disconnect(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean terminateApplication(String name, boolean normal, String exitText) - throws IOException, SmartFrogException { - Session session = null; - try { - log.info("Terminating application " + name + " for " + exitText); - session = demandCreateSession(hostname); - ArrayList<String> commandsList = new ArrayList<String>(1); - String sshCommand = makeSFCommand("sfTerminate") + " " + "localhost" + " " + name; - log.info("executing: " + sshCommand); - commandsList.add(sshCommand); - commandsList.add("exit"); - return sshExec(session, commandsList, false) == 0; - } catch (JSchException e) { - String connectionDetails = getConnectionDetails(); - log.error("Failed to terminate "+ name+ " on " + connectionDetails + " : " + e, e); - throw forward(e, connectionDetails); - } finally { - endSession(session); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void pingApplication(String name) throws IOException, SmartFrogException { - } - - /** - * {@inheritDoc} - */ - @Override - public String getServiceDescription() throws IOException, SmartFrogException { - return "SSH to " + hostname; - } - - @Override - public String getApplicationDescription(String name) throws IOException, SmartFrogException { - return ""; - } - - /** - * {@inheritDoc} - */ - @Override - public void terminate() throws IOException, SmartFrogException { - } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |