From e7ddf0b3a271a2f22108ee5b9fba69888f5c78ec Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 14 Jun 2009 21:23:54 +0000 Subject: [PATCH] Introduce revision build numbers Introduce VBox Lib Introduce SSH support git-svn-id: https://svn.argeo.org/slc/trunk@2550 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- demo/pom.xml | 6 + demo/site/pom.xml | 2 +- pom.xml | 24 +++ runtime/org.argeo.slc.launcher/pom.xml | 25 +-- .../org/argeo/slc/deploy/DeployedSystem.java | 4 + .../slc/deploy/ModularDeployedSystem.java | 8 + .../java/org/argeo/slc/deploy/Module.java | 9 + .../argeo/slc/jms/JmsAttachmentUploader.java | 66 +++--- .../slc/equinox/ExecutionCommandProvider.java | 200 ++++++++++-------- .../java/org/argeo/slc/osgi/OsgiBundle.java | 30 +++ .../argeo/slc/osgi/OsgiExecutionLauncher.java | 155 ++++++++++++++ .../java/org/argeo/slc/osgi/OsgiRuntime.java | 38 ++++ .../resources/META-INF/spring/manager.xml | 13 ++ .../main/resources/META-INF/spring/osgi.xml | 3 +- runtime/org.argeo.slc.support.simple/pom.xml | 6 + .../slc/core/execution/tasks/MethodCall.java | 38 ++++ .../slc/core/execution/tasks/SystemCall.java | 9 + .../org/argeo/slc/jsch/AbstractJschTask.java | 64 ++++++ .../java/org/argeo/slc/jsch/RemoteExec.java | 108 ++++++++++ .../main/java/org/argeo/slc/jsch/ScpTo.java | 108 ++++++++++ .../org/argeo/slc/jsch/SimpleUserInfo.java | 133 ++++++++++++ .../java/org/argeo/slc/jsch/SshTarget.java | 46 ++++ .../org/argeo/slc/lib/vbox/VBoxManager.java | 63 ++++++ .../java/org/argeo/slc/lib/vbox/VBoxNat.java | 26 +++ .../argeo/slc/lib/vbox/VBoxPortMapping.java | 33 +++ runtime/pom.xml | 47 +++- 26 files changed, 1117 insertions(+), 147 deletions(-) create mode 100644 runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/ModularDeployedSystem.java create mode 100644 runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/Module.java create mode 100644 runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiBundle.java create mode 100644 runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiExecutionLauncher.java create mode 100644 runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiRuntime.java create mode 100644 runtime/org.argeo.slc.support.equinox/src/main/resources/META-INF/spring/manager.xml create mode 100644 runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/MethodCall.java create mode 100644 runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/AbstractJschTask.java create mode 100644 runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/RemoteExec.java create mode 100644 runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/ScpTo.java create mode 100644 runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/SimpleUserInfo.java create mode 100644 runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/SshTarget.java create mode 100644 runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxManager.java create mode 100644 runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxNat.java create mode 100644 runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxPortMapping.java diff --git a/demo/pom.xml b/demo/pom.xml index 684466dbf..dbff147d6 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -69,6 +69,12 @@ org.argeo.slc.runtime org.argeo.slc.osgiboot + + + org.argeo.slc.dep + org.argeo.slc.dep.agent + ${project.version} + diff --git a/demo/site/pom.xml b/demo/site/pom.xml index 02825209f..2c48af97d 100644 --- a/demo/site/pom.xml +++ b/demo/site/pom.xml @@ -13,7 +13,7 @@ - org.argeo.slc.maven + org.argeo.maven.plugins maven-argeo-osgi-plugin true diff --git a/pom.xml b/pom.xml index dc33ca5ce..11f2b9681 100644 --- a/pom.xml +++ b/pom.xml @@ -148,6 +148,24 @@ limitations under the License. + + org.codehaus.mojo + buildnumber-maven-plugin + 1.0-beta-3 + + + validate + + create + + + + + false + false + true + + org.apache.maven.plugins maven-resources-plugin @@ -792,6 +810,12 @@ limitations under the License. 1.3.0 + + + com.jcraft.jsch + com.springsource.com.jcraft.jsch + 0.1.25 + diff --git a/runtime/org.argeo.slc.launcher/pom.xml b/runtime/org.argeo.slc.launcher/pom.xml index dc6398adc..0ca25a959 100644 --- a/runtime/org.argeo.slc.launcher/pom.xml +++ b/runtime/org.argeo.slc.launcher/pom.xml @@ -63,34 +63,15 @@ - - org.argeo.slc.runtime - org.argeo.slc.specs - - org.argeo.dep.osgi org.argeo.dep.osgi.commons.cli - org.springframework - org.springframework.context - - - - org.apache.commons - com.springsource.org.apache.commons.logging + org.argeo.slc.dep + org.argeo.slc.dep.agent + ${project.version} - - org.apache.log4j - com.springsource.org.apache.log4j - - - - org.eclipse.osgi - org.eclipse.osgi - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/DeployedSystem.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/DeployedSystem.java index 1642b095c..be28154fe 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/DeployedSystem.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/DeployedSystem.java @@ -4,11 +4,15 @@ import org.argeo.slc.build.Distribution; /** An instance of a software system. */ public interface DeployedSystem extends TargetData { + /** Unique ID for this system instance. */ public String getDeployedSystemId(); + /** Underlying packages */ public Distribution getDistribution(); + /** Data required to initialize the instance (e.g. DB dump, etc.). */ public DeploymentData getDeploymentData(); + /** Resources required by the system (ports, disk location, etc.) */ public TargetData getTargetData(); } diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/ModularDeployedSystem.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/ModularDeployedSystem.java new file mode 100644 index 000000000..346d2bcaa --- /dev/null +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/ModularDeployedSystem.java @@ -0,0 +1,8 @@ +package org.argeo.slc.deploy; + +import java.util.List; + +public interface ModularDeployedSystem extends DeployedSystem { + /** List the underlying deployed modules (in real time) */ + public List listModules(); +} diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/Module.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/Module.java new file mode 100644 index 000000000..897358e0c --- /dev/null +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/Module.java @@ -0,0 +1,9 @@ +package org.argeo.slc.deploy; + +import org.argeo.slc.build.Distribution; + +public interface Module { + public String getName(); + public String getVersion(); + public Distribution getDistribution(); +} diff --git a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsAttachmentUploader.java b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsAttachmentUploader.java index 44dcd3e1b..bc1391335 100644 --- a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsAttachmentUploader.java +++ b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsAttachmentUploader.java @@ -10,14 +10,20 @@ import javax.jms.Message; import javax.jms.Session; import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; import org.argeo.slc.core.attachment.Attachment; import org.argeo.slc.core.attachment.AttachmentUploader; import org.springframework.core.io.Resource; +import org.springframework.jms.JmsException; import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.MessageCreator; public class JmsAttachmentUploader implements AttachmentUploader { + private final static Log log = LogFactory + .getLog(JmsAttachmentUploader.class); + public final static String ATTACHMENT_ID = "slc_attachmentId"; public final static String ATTACHMENT_NAME = "slc_attachmentName"; public final static String ATTACHMENT_CONTENT_TYPE = "slc_attachmentContentType"; @@ -26,36 +32,44 @@ public class JmsAttachmentUploader implements AttachmentUploader { private Destination destination; public void upload(final Attachment attachment, final Resource resource) { - jmsTemplate.send(destination, new MessageCreator() { + try { + jmsTemplate.send(destination, new MessageCreator() { - public Message createMessage(Session session) throws JMSException { - BytesMessage message = session.createBytesMessage(); - message.setStringProperty(ATTACHMENT_ID, attachment.getUuid()); - message - .setStringProperty(ATTACHMENT_NAME, attachment - .getName()); - message.setStringProperty(ATTACHMENT_CONTENT_TYPE, attachment - .getContentType()); + public Message createMessage(Session session) + throws JMSException { + BytesMessage message = session.createBytesMessage(); + message.setStringProperty(ATTACHMENT_ID, attachment + .getUuid()); + message.setStringProperty(ATTACHMENT_NAME, attachment + .getName()); + message.setStringProperty(ATTACHMENT_CONTENT_TYPE, + attachment.getContentType()); - InputStream in = null; - try { - in = resource.getInputStream(); - byte[] buffer = new byte[1024 * 1024]; - int read = -1; - while ((read = in.read(buffer)) > 0) { - message.writeBytes(buffer, 0, read); + InputStream in = null; + try { + in = resource.getInputStream(); + byte[] buffer = new byte[1024 * 1024]; + int read = -1; + while ((read = in.read(buffer)) > 0) { + message.writeBytes(buffer, 0, read); + } + } catch (IOException e) { + throw new SlcException( + "Cannot write into byte message for attachment " + + attachment + " and resource " + + resource, e); + } finally { + IOUtils.closeQuietly(in); } - } catch (IOException e) { - throw new SlcException( - "Cannot write into byte message for attachment " - + attachment + " and resource " + resource, - e); - } finally { - IOUtils.closeQuietly(in); + return message; } - return message; - } - }); + }); + } catch (JmsException e) { + if (log.isTraceEnabled()) + log.debug("Cannot upload", e); + else if (log.isDebugEnabled()) + log.debug("Cannot upload: " + e.getMessage()); + } } diff --git a/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/equinox/ExecutionCommandProvider.java b/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/equinox/ExecutionCommandProvider.java index 462e29016..3c6912b21 100644 --- a/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/equinox/ExecutionCommandProvider.java +++ b/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/equinox/ExecutionCommandProvider.java @@ -6,24 +6,33 @@ import org.argeo.slc.SlcException; import org.argeo.slc.execution.ExecutionFlowDescriptor; import org.argeo.slc.execution.ExecutionModule; import org.argeo.slc.osgi.BundlesManager; +import org.argeo.slc.osgi.OsgiExecutionLauncher; +import org.eclipse.core.runtime.adaptor.EclipseStarter; +import org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher; import org.eclipse.osgi.framework.console.CommandInterpreter; import org.eclipse.osgi.framework.console.CommandProvider; +import org.eclipse.osgi.framework.launcher.Launcher; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; +import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.osgi.context.BundleContextAware; public class ExecutionCommandProvider implements CommandProvider, - BundleContextAware { + InitializingBean { private final static Log log = LogFactory .getLog(ExecutionCommandProvider.class); - private BundleContext bundleContext; - private BundlesManager bundlesManager; + // private BundleContext bundleContext; + // private BundlesManager bundlesManager; - private String lastModuleName = null; - private String lastExecutionName = null; + private OsgiExecutionLauncher executionLauncher; + + private OsgiExecutionLauncher.Launch lastLaunch = null; + + // private String lastModuleName = null; + // private String lastExecutionName = null; /** @deprecated Use slc command instead. */ public Object _slc_exec(CommandInterpreter ci) { @@ -34,8 +43,9 @@ public class ExecutionCommandProvider implements CommandProvider, // TODO: check version String firstArg = ci.nextArgument(); if (firstArg == null) { - if (lastModuleName != null) { - String cmd = "slc " + lastModuleName + " " + lastExecutionName; + if (lastLaunch != null) { + String cmd = "slc " + lastLaunch.getModuleName() + " " + + lastLaunch.getExecutionName(); if (log.isDebugEnabled()) log.debug("Execute again last command: " + cmd); return ci.execute(cmd); @@ -46,86 +56,70 @@ public class ExecutionCommandProvider implements CommandProvider, } String executionName = ci.nextArgument(); - String moduleName = null; - - // First check whether we have a bundleId - Long bundleId = null; - try { - bundleId = Long.parseLong(firstArg); - } catch (NumberFormatException e) { - // silent - } + launch(firstArg, executionName); + /* + * String moduleName = null; + * + * // First check whether we have a bundleId Long bundleId = null; try { + * bundleId = Long.parseLong(firstArg); } catch (NumberFormatException + * e) { // silent } + * + * // Look for bundle names containing pattern Bundle bundle = null; if + * (bundleId != null) { bundle = bundleContext.getBundle(bundleId); } + * else { for (Bundle b : bundleContext.getBundles()) { if + * (b.getSymbolicName().contains(firstArg)) { bundle = b; break; } } } + * + * if (bundle != null) { moduleName = bundle.getSymbolicName(); + * lastModuleName = moduleName; lastExecutionName = executionName; } + * else { log + * .warn("Could not find any execution module matching these requirements." + * ); return null; } + * + * // Find module ExecutionModule module = null; ServiceReference + * serviceRef = null; try { bundlesManager.stopSynchronous(bundle); + * bundlesManager.updateSynchronous(bundle); // Refresh in case there + * are fragments bundlesManager.refreshSynchronous(bundle); + * bundlesManager.startSynchronous(bundle); + * + * String filter = "(Bundle-SymbolicName=" + moduleName + ")"; // Wait + * for application context to be ready + * bundlesManager.getServiceRefSynchronous(ApplicationContext.class + * .getName(), filter); + * + * if (log.isDebugEnabled()) log.debug("Bundle " + + * bundle.getSymbolicName() + " ready to be used at latest version."); + * + * ServiceReference[] sfs = bundlesManager.getServiceRefSynchronous( + * ExecutionModule.class.getName(), filter); + * + * if (sfs.length > 1) log + * .warn("More than one execution module service found in module " + + * moduleName); + * + * if (sfs.length > 0) { serviceRef = sfs[0]; module = (ExecutionModule) + * bundleContext.getService(serviceRef); } + * + * if (module != null) { ExecutionFlowDescriptor descriptor = new + * ExecutionFlowDescriptor(); descriptor.setName(executionName); + * module.execute(descriptor); log.info("Executed " + executionName + + * " from " + moduleName); } + * + * } catch (Exception e) { throw new + * SlcException("Cannot find or update module.", e); } finally { if + * (serviceRef != null) bundleContext.ungetService(serviceRef); } + */ - // Look for bundle names containing pattern - Bundle bundle = null; - if (bundleId != null) { - bundle = bundleContext.getBundle(bundleId); - } else { - for (Bundle b : bundleContext.getBundles()) { - if (b.getSymbolicName().contains(firstArg)) { - bundle = b; - break; - } - } - } - - if (bundle != null) { - moduleName = bundle.getSymbolicName(); - lastModuleName = moduleName; - lastExecutionName = executionName; - } else { - log - .warn("Could not find any execution module matching these requirements."); - return null; - } - - // Find module - ExecutionModule module = null; - ServiceReference serviceRef = null; - try { - bundlesManager.stopSynchronous(bundle); - bundlesManager.updateSynchronous(bundle); - // Refresh in case there are fragments - bundlesManager.refreshSynchronous(bundle); - bundlesManager.startSynchronous(bundle); - - String filter = "(Bundle-SymbolicName=" + moduleName + ")"; - // Wait for application context to be ready - bundlesManager.getServiceRefSynchronous(ApplicationContext.class - .getName(), filter); - - if (log.isDebugEnabled()) - log.debug("Bundle " + bundle.getSymbolicName() - + " ready to be used at latest version."); - - ServiceReference[] sfs = bundlesManager.getServiceRefSynchronous( - ExecutionModule.class.getName(), filter); - - if (sfs.length > 1) - log - .warn("More than one execution module service found in module " - + moduleName); - - if (sfs.length > 0) { - serviceRef = sfs[0]; - module = (ExecutionModule) bundleContext.getService(serviceRef); - } + return "COMMAND COMPLETED"; + } - if (module != null) { - ExecutionFlowDescriptor descriptor = new ExecutionFlowDescriptor(); - descriptor.setName(executionName); - module.execute(descriptor); - log.info("Executed " + executionName + " from " + moduleName); - } + protected void launch(String firstArg, String executionName) { + lastLaunch = executionLauncher.findLaunch(firstArg, executionName); + if (lastLaunch == null) + throw new SlcException("Cannot find launch for " + firstArg + " " + + executionName); - } catch (Exception e) { - throw new SlcException("Cannot find or update module.", e); - } finally { - if (serviceRef != null) - bundleContext.ungetService(serviceRef); - } + executionLauncher.launch(lastLaunch); - return "COMMAND COMPLETED"; } public String getHelp() { @@ -137,12 +131,44 @@ public class ExecutionCommandProvider implements CommandProvider, } - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; + public void setExecutionLauncher(OsgiExecutionLauncher launcher) { + this.executionLauncher = launcher; } - public void setBundlesManager(BundlesManager bundlesManager) { - this.bundlesManager = bundlesManager; + public void afterPropertiesSet() throws Exception { + final String module = System.getProperty("slc.launch.module"); + final String executionName = System.getProperty("slc.launch.execution"); + if (module != null) { + new Thread() { + + @Override + public void run() { + try { + launch(module, executionName); + // in case of failure OSGi runtime stays up and last + // launch can be used to debug by calling 'slc' + } catch (Exception e) { + throw new SlcException("Error when executing " + + executionName + " on " + module, e); + } + try { + EclipseStarter.shutdown(); + } catch (Exception e) { + throw new SlcException("Cannot shutdown equinox.", e); + } + } + + }.start(); + } + } + // public void setBundleContext(BundleContext bundleContext) { + // this.bundleContext = bundleContext; + // } + + // public void setBundlesManager(BundlesManager bundlesManager) { + // this.bundlesManager = bundlesManager; + // } + } diff --git a/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiBundle.java b/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiBundle.java new file mode 100644 index 000000000..42663cc6d --- /dev/null +++ b/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiBundle.java @@ -0,0 +1,30 @@ +package org.argeo.slc.osgi; + +import org.argeo.slc.build.Distribution; +import org.argeo.slc.deploy.DeployedSystem; +import org.argeo.slc.deploy.DeploymentData; +import org.argeo.slc.deploy.TargetData; + +public class OsgiBundle implements DeployedSystem { + + public String getDeployedSystemId() { + // TODO Auto-generated method stub + return null; + } + + public DeploymentData getDeploymentData() { + // TODO Auto-generated method stub + return null; + } + + public Distribution getDistribution() { + // TODO Auto-generated method stub + return null; + } + + public TargetData getTargetData() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiExecutionLauncher.java b/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiExecutionLauncher.java new file mode 100644 index 000000000..5baa91be8 --- /dev/null +++ b/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiExecutionLauncher.java @@ -0,0 +1,155 @@ +package org.argeo.slc.osgi; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionFlowDescriptor; +import org.argeo.slc.execution.ExecutionModule; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.springframework.context.ApplicationContext; +import org.springframework.osgi.context.BundleContextAware; + +public class OsgiExecutionLauncher implements BundleContextAware { + private final static Log log = LogFactory + .getLog(OsgiExecutionLauncher.class); + + private BundleContext bundleContext; + private BundlesManager bundlesManager; + + public Launch findLaunch(String firstArg, String executionName) { + Launch launch = new Launch(); + + // String moduleName = null; + + // First check whether we have a bundleId + Long bundleId = null; + try { + bundleId = Long.parseLong(firstArg); + } catch (NumberFormatException e) { + // silent + } + + // Look for bundle names containing pattern + Bundle bundle = null; + if (bundleId != null) { + bundle = bundleContext.getBundle(bundleId); + } else { + for (Bundle b : bundleContext.getBundles()) { + if (b.getSymbolicName().contains(firstArg)) { + bundle = b; + break; + } + } + } + + if (bundle != null) { + launch.setBundleId(bundle.getBundleId()); + launch.setModuleName(bundle.getSymbolicName()); + launch.setExecutionName(executionName); + return launch; + } else { + log + .warn("Could not find any execution module matching these requirements."); + return null; + } + + } + + public void launch(Launch launch) { + Bundle bundle = bundleContext.getBundle(launch.getBundleId()); + + // Find module + ExecutionModule module = null; + ServiceReference serviceRef = null; + try { + bundlesManager.stopSynchronous(bundle); + bundlesManager.updateSynchronous(bundle); + // Refresh in case there are fragments + bundlesManager.refreshSynchronous(bundle); + bundlesManager.startSynchronous(bundle); + + String filter = "(Bundle-SymbolicName=" + launch.getModuleName() + + ")"; + // Wait for application context to be ready + bundlesManager.getServiceRefSynchronous(ApplicationContext.class + .getName(), filter); + + if (log.isDebugEnabled()) + log.debug("Bundle " + bundle.getSymbolicName() + + " ready to be used at latest version."); + + ServiceReference[] sfs = bundlesManager.getServiceRefSynchronous( + ExecutionModule.class.getName(), filter); + + if (sfs.length > 1) + log + .warn("More than one execution module service found in module " + + launch.getModuleName()); + + if (sfs.length > 0) { + serviceRef = sfs[0]; + module = (ExecutionModule) bundleContext.getService(serviceRef); + } + + if (module != null) { + ExecutionFlowDescriptor descriptor = new ExecutionFlowDescriptor(); + descriptor.setName(launch.getExecutionName()); + module.execute(descriptor); + log.info("Executed " + launch.getExecutionName() + " from " + + launch.getExecutionName()); + } + + } catch (Exception e) { + throw new SlcException("Cannot launch " + launch, e); + } finally { + if (serviceRef != null) + bundleContext.ungetService(serviceRef); + } + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + public void setBundlesManager(BundlesManager bundlesManager) { + this.bundlesManager = bundlesManager; + } + + public static class Launch { + private Long bundleId; + private String moduleName; + private String executionName; + + public Long getBundleId() { + return bundleId; + } + + public void setBundleId(Long bundleId) { + this.bundleId = bundleId; + } + + public String getModuleName() { + return moduleName; + } + + public void setModuleName(String moduleName) { + this.moduleName = moduleName; + } + + public String getExecutionName() { + return executionName; + } + + public void setExecutionName(String executionName) { + this.executionName = executionName; + } + + @Override + public String toString() { + return moduleName + " " + executionName; + } + + } +} diff --git a/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiRuntime.java b/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiRuntime.java new file mode 100644 index 000000000..364854605 --- /dev/null +++ b/runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/osgi/OsgiRuntime.java @@ -0,0 +1,38 @@ +package org.argeo.slc.osgi; + +import java.util.List; + +import org.argeo.slc.build.Distribution; +import org.argeo.slc.deploy.DeployedSystem; +import org.argeo.slc.deploy.DeploymentData; +import org.argeo.slc.deploy.ModularDeployedSystem; +import org.argeo.slc.deploy.TargetData; + +public class OsgiRuntime implements ModularDeployedSystem { + + public List listModules() { + // TODO Auto-generated method stub + return null; + } + + public String getDeployedSystemId() { + // TODO Auto-generated method stub + return null; + } + + public DeploymentData getDeploymentData() { + // TODO Auto-generated method stub + return null; + } + + public Distribution getDistribution() { + // TODO Auto-generated method stub + return null; + } + + public TargetData getTargetData() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/runtime/org.argeo.slc.support.equinox/src/main/resources/META-INF/spring/manager.xml b/runtime/org.argeo.slc.support.equinox/src/main/resources/META-INF/spring/manager.xml new file mode 100644 index 000000000..dcf58c1ac --- /dev/null +++ b/runtime/org.argeo.slc.support.equinox/src/main/resources/META-INF/spring/manager.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.equinox/src/main/resources/META-INF/spring/osgi.xml b/runtime/org.argeo.slc.support.equinox/src/main/resources/META-INF/spring/osgi.xml index 6ecec1359..b3e667aab 100644 --- a/runtime/org.argeo.slc.support.equinox/src/main/resources/META-INF/spring/osgi.xml +++ b/runtime/org.argeo.slc.support.equinox/src/main/resources/META-INF/spring/osgi.xml @@ -8,9 +8,8 @@ - + - \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.simple/pom.xml b/runtime/org.argeo.slc.support.simple/pom.xml index 98dddc130..9829bb47e 100644 --- a/runtime/org.argeo.slc.support.simple/pom.xml +++ b/runtime/org.argeo.slc.support.simple/pom.xml @@ -109,5 +109,11 @@ com.springsource.org.apache.commons.collections + + + com.jcraft.jsch + com.springsource.com.jcraft.jsch + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/MethodCall.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/MethodCall.java new file mode 100644 index 000000000..88aeb4716 --- /dev/null +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/MethodCall.java @@ -0,0 +1,38 @@ +package org.argeo.slc.core.execution.tasks; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class MethodCall implements Runnable { + private Object target; + private String method; + private List args = new ArrayList(); + + public void run() { + Assert.notNull(target, "target"); + Assert.notNull(method, "method"); + Method methodRef = ReflectionUtils + .findMethod(target.getClass(), method); + if (args.size() == 0) + ReflectionUtils.invokeMethod(methodRef, target); + else + ReflectionUtils.invokeMethod(methodRef, methodRef, args.toArray()); + } + + public void setTarget(Object target) { + this.target = target; + } + + public void setMethod(String method) { + this.method = method; + } + + public void setArgs(List args) { + this.args = args; + } + +} diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java index 0ea1f7bee..e45ae540d 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java @@ -56,6 +56,15 @@ public class SystemCall extends TreeSRelatedHelper implements Runnable, private TestResult testResult; + public SystemCall() { + + } + + public SystemCall(List command) { + super(); + this.command = command; + } + public void run() { // Log writers final Writer stdOutWriter; diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/AbstractJschTask.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/AbstractJschTask.java new file mode 100644 index 000000000..9567d8f09 --- /dev/null +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/AbstractJschTask.java @@ -0,0 +1,64 @@ +package org.argeo.slc.jsch; + +import java.io.IOException; +import java.io.InputStream; + +import org.argeo.slc.SlcException; + +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; + +public abstract class AbstractJschTask implements Runnable { + private SshTarget sshTarget; + + protected Session openSession() { + try { + JSch jsch = new JSch(); + Session session = jsch.getSession(getSshTarget().getUser(), + getSshTarget().getHost(), getSshTarget().getPort()); + + session.setUserInfo(getSshTarget().getUserInfo()); + session.connect(); + return session; + } catch (JSchException e) { + throw new SlcException("Could not open session to " + + getSshTarget(), e); + } + } + + protected void checkAck(InputStream in) throws IOException { + int b = in.read(); + // b may be 0 for success, + // 1 for error, + // 2 for fatal error, + // -1 + if (b == 0) + return; + else if (b == -1) + throw new SlcException("SSH ack returned -1"); + else if (b == 1 || b == 2) { + StringBuffer sb = new StringBuffer(); + int c; + do { + c = in.read(); + sb.append((char) c); + } while (c != '\n'); + if (b == 1) { // error + throw new SlcException("SSH ack error: " + sb.toString()); + } + if (b == 2) { // fatal error + throw new SlcException("SSH fatal error: " + sb.toString()); + } + } + } + + public SshTarget getSshTarget() { + return sshTarget; + } + + public void setSshTarget(SshTarget sshTarget) { + this.sshTarget = sshTarget; + } + +} diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/RemoteExec.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/RemoteExec.java new file mode 100644 index 000000000..80b651398 --- /dev/null +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/RemoteExec.java @@ -0,0 +1,108 @@ +package org.argeo.slc.jsch; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; + +import com.jcraft.jsch.Channel; +import com.jcraft.jsch.ChannelExec; +import com.jcraft.jsch.Session; + +public class RemoteExec extends AbstractJschTask { + private final static Log log = LogFactory.getLog(RemoteExec.class); + + private List commands = new ArrayList(); + private String command; + + public void run() { + Session session = openSession(); + if (command != null) { + if (commands.size() != 0) + throw new SlcException( + "Specify either a single command or a list of commands."); + remoteExec(session, command); + } else { + if (commands.size() == 0) + throw new SlcException( + "Neither a single command or a list of commands has been specified."); + + for (String cmd : commands) { + remoteExec(session, cmd); + } + } + session.disconnect(); + } + + protected void remoteExec(Session session, String command) { + BufferedReader execIn = null; + try { + Channel channel = session.openChannel("exec"); + ((ChannelExec) channel).setCommand(command); + + // X Forwarding + // channel.setXForwarding(true); + + // channel.setInputStream(System.in); + channel.setInputStream(null); + + // channel.setOutputStream(System.out); + + // FileOutputStream fos=new FileOutputStream("/tmp/stderr"); + // ((ChannelExec)channel).setErrStream(fos); + ((ChannelExec) channel).setErrStream(System.err); + + InputStream in = channel.getInputStream(); + + if (log.isDebugEnabled()) + log.debug("Exec '" + command + "' on " + getSshTarget() + "..."); + + channel.connect(); + + // byte[] tmp = new byte[1024]; + while (true) { + execIn = new BufferedReader(new InputStreamReader(in)); + String line = null; + while ((line = execIn.readLine()) != null) { + log.info(line); + } + // while (in.available() > 0) { + // int i = in.read(tmp, 0, 1024); + // if (i < 0) + // break; + // log.info(new String(tmp, 0, i)); + // } + if (channel.isClosed()) { + log.info("Remote execution exit status: " + + channel.getExitStatus()); + break; + } + try { + Thread.sleep(1000); + } catch (Exception ee) { + } + } + channel.disconnect(); + } catch (Exception e) { + throw new SlcException("Cannot execute remotely '" + command + + "' on " + getSshTarget(), e); + } finally { + IOUtils.closeQuietly(execIn); + } + } + + public void setCommand(String command) { + this.command = command; + } + + public void setCommands(List commands) { + this.commands = commands; + } + +} diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/ScpTo.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/ScpTo.java new file mode 100644 index 000000000..d10125fe7 --- /dev/null +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/ScpTo.java @@ -0,0 +1,108 @@ +package org.argeo.slc.jsch; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.springframework.core.io.Resource; + +import com.jcraft.jsch.Channel; +import com.jcraft.jsch.ChannelExec; +import com.jcraft.jsch.Session; + +public class ScpTo extends AbstractJschTask { + private final static Log log = LogFactory.getLog(ScpTo.class); + + private Resource localFile; + private String remoteFile; + + public void run() { + InputStream in = null; + OutputStream channelOut; + InputStream channelIn; + + Session session = openSession(); + try { + + // exec 'scp -t rfile' remotely + String command = "scp -p -t " + remoteFile; + Channel channel = session.openChannel("exec"); + ((ChannelExec) channel).setCommand(command); + + // get I/O streams for remote scp + channelOut = channel.getOutputStream(); + channelIn = channel.getInputStream(); + + channel.connect(); + checkAck(channelIn); + + // send "C0644 filesize filename", where filename should not include + // '/' + File lFile = localFile.getFile(); + long filesize = lFile.length(); + command = "C0644 " + filesize + " "; + int index = lFile.getPath().lastIndexOf('/'); + if (index > 0) { + command += lFile.getPath().substring(index + 1); + } else { + command += lFile.getPath(); + } + command += "\n"; + + channelOut.write(command.getBytes()); + channelOut.flush(); + checkAck(channelIn); + + if (log.isDebugEnabled()) + log.debug("Start copy of " + localFile + " to " + remoteFile + + " on " + getSshTarget() + "..."); + + // send a content of lfile + in = localFile.getInputStream(); + byte[] buf = new byte[1024]; + long cycleCount = 0; + while (true) { + int len = in.read(buf, 0, buf.length); + if (len <= 0) + break; + channelOut.write(buf, 0, len); // out.flush(); + if ((cycleCount % 1024) == 0)// each 1 MB + System.out.print('#'); + cycleCount++; + } + // send '\0' + buf[0] = 0; + channelOut.write(buf, 0, 1); + channelOut.flush(); + checkAck(channelIn); + + if (log.isDebugEnabled()) + log.debug("Finished copy of " + localFile + " to " + remoteFile + + " on " + getSshTarget() + "..."); + + IOUtils.closeQuietly(channelOut); + + channel.disconnect(); + session.disconnect(); + + } catch (Exception e) { + throw new SlcException("Cannot copy " + localFile + " to " + + remoteFile, e); + } finally { + IOUtils.closeQuietly(in); + } + } + + public void setLocalFile(Resource localFile) { + this.localFile = localFile; + } + + public void setRemoteFile(String remoteFile) { + this.remoteFile = remoteFile; + } + +} diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/SimpleUserInfo.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/SimpleUserInfo.java new file mode 100644 index 000000000..3691bb675 --- /dev/null +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/SimpleUserInfo.java @@ -0,0 +1,133 @@ +package org.argeo.slc.jsch; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PushbackInputStream; +import java.util.Arrays; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; + +import com.jcraft.jsch.UserInfo; + +public class SimpleUserInfo implements UserInfo { + private Boolean permissive = true; + private final static Log log = LogFactory.getLog(SimpleUserInfo.class); + + private String password; + private char[] passwordSafe; + + public void setPassword(String password) { + this.password = password; + } + + public String getPassphrase() { + return null; + } + + public String getPassword() { + if (passwordSafe != null) + return new String(passwordSafe); + return password; + } + + public boolean promptPassphrase(String message) { + return true; + } + + public boolean promptPassword(String message) { + log.info(message); + if (permissive) + return true; + else { + passwordSafe = readPassword(System.in); + return passwordSafe != null; + } + } + + public boolean promptYesNo(String message) { + String msg = message + " (y/n): "; + if (permissive) { + log.info(msg + "y"); + return true; + } else { + log.info(msg); + char c; + try { + c = (char) System.in.read(); + } catch (IOException e) { + throw new SlcException("Cannot read stdin", e); + } + if (c == 'y') + return true; + else + return false; + } + } + + public void showMessage(String message) { + log.info(message); + } + + public void setPermissive(Boolean permissive) { + this.permissive = permissive; + } + + protected char[] readPassword(InputStream in) { + + try { + char[] lineBuffer; + char[] buf; + //int i; + + buf = lineBuffer = new char[128]; + + int room = buf.length; + int offset = 0; + int c; + + loop: while (true) { + switch (c = in.read()) { + case -1: + case '\n': + break loop; + + case '\r': + int c2 = in.read(); + if ((c2 != '\n') && (c2 != -1)) { + if (!(in instanceof PushbackInputStream)) { + in = new PushbackInputStream(in); + } + ((PushbackInputStream) in).unread(c2); + } else + break loop; + + default: + if (--room < 0) { + buf = new char[offset + 128]; + room = buf.length - offset - 1; + System.arraycopy(lineBuffer, 0, buf, 0, offset); + Arrays.fill(lineBuffer, ' '); + lineBuffer = buf; + } + buf[offset++] = (char) c; + break; + } + } + + if (offset == 0) { + return null; + } + + char[] ret = new char[offset]; + System.arraycopy(buf, 0, ret, 0, offset); + Arrays.fill(buf, ' '); + + return ret; + } catch (IOException e) { + throw new SlcException("Cannot read password.", e); + } + } + +} diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/SshTarget.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/SshTarget.java new file mode 100644 index 000000000..8afe5ec4a --- /dev/null +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/SshTarget.java @@ -0,0 +1,46 @@ +package org.argeo.slc.jsch; + +import com.jcraft.jsch.UserInfo; + +public class SshTarget { + private String host; + private Integer port; + private String user; + private UserInfo userInfo; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public UserInfo getUserInfo() { + return userInfo; + } + + public void setUserInfo(UserInfo userInfo) { + this.userInfo = userInfo; + } + + public String toString() { + return "ssh:" + getUser() + "@" + getHost() + ":" + getPort(); + } +} diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxManager.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxManager.java new file mode 100644 index 000000000..c912ed527 --- /dev/null +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxManager.java @@ -0,0 +1,63 @@ +package org.argeo.slc.lib.vbox; + +import java.util.ArrayList; +import java.util.List; + +import org.argeo.slc.core.execution.tasks.SystemCall; + +public class VBoxManager { + private String machineName; + private String executable = "VBoxManage"; + + private List nats = new ArrayList(); + + public void applyNats() { + for (VBoxNat vBoxNat : nats) + for (String id : vBoxNat.getMappings().keySet()) { + VBoxPortMapping mapping = vBoxNat.getMappings().get(id); + new SystemCall(createNatCommand(id, vBoxNat.getDevice(), + "Protocol", mapping.getProtocol())).run(); + new SystemCall(createNatCommand(id, vBoxNat.getDevice(), + "GuestPort", mapping.getGuest())).run(); + new SystemCall(createNatCommand(id, vBoxNat.getDevice(), + "HostPort", mapping.getHost())).run(); + } + } + + protected List createNatCommand(String id, String device, + String cfgKey, String value) { + List cmd = new ArrayList(); + cmd.add(executable); + cmd.add("setextradata"); + cmd.add(machineName); + cmd.add("VBoxInternal/Devices/" + device + "/0/LUN#0/Config/" + id + + "/" + cfgKey); + cmd.add(value); + return cmd; + } + + public String getMachineName() { + return machineName; + } + + public void setMachineName(String machineName) { + this.machineName = machineName; + } + + public String getExecutable() { + return executable; + } + + public void setExecutable(String executable) { + this.executable = executable; + } + + public List getNats() { + return nats; + } + + public void setNats(List boxNats) { + nats = boxNats; + } + +} diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxNat.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxNat.java new file mode 100644 index 000000000..96c69d7e5 --- /dev/null +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxNat.java @@ -0,0 +1,26 @@ +package org.argeo.slc.lib.vbox; + +import java.util.Map; + +/** The NAT mapping table */ +public class VBoxNat { + private String device = "pcnet"; + private Map mappings; + + public String getDevice() { + return device; + } + + public void setDevice(String device) { + this.device = device; + } + + public Map getMappings() { + return mappings; + } + + public void setMappings(Map mappings) { + this.mappings = mappings; + } + +} diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxPortMapping.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxPortMapping.java new file mode 100644 index 000000000..54d29ac9b --- /dev/null +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/vbox/VBoxPortMapping.java @@ -0,0 +1,33 @@ +package org.argeo.slc.lib.vbox; + +/** The mapping of one port.*/ +public class VBoxPortMapping { + private String protocol = "TCP"; + private String guest; + private String host; + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String type) { + this.protocol = type; + } + + public String getGuest() { + return guest; + } + + public void setGuest(String guest) { + this.guest = guest; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + +} diff --git a/runtime/pom.xml b/runtime/pom.xml index cfe68ab31..2230e85dd 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -46,6 +46,7 @@ target/classes/META-INF + ${project.version}-r${buildNumber} ${pom.artifactId} <_removeheaders>Bnd-LastModified @@ -64,13 +65,41 @@ + + + release + + + + org.apache.felix + maven-bundle-plugin + ${version.maven-bundle-plugin} + true + + target/classes/META-INF + + ${project.version}.r${buildNumber} + ${pom.artifactId} + <_removeheaders>Bnd-LastModified + + + + + bundle-manifest + process-classes + + manifest + + + + + + + + --> + -- 2.39.2