Author: angelos
Date: Sun Mar 20 19:23:04 2011
New Revision: 1083544
URL: http://svn.apache.org/viewvc?rev=1083544&view=rev
Log:
Added an implementation of the NodeLauncher that uses JClouds to launch Amazon instances.
Added:
incubator/ace/trunk/ace-nodelauncher-amazon/
incubator/ace/trunk/ace-nodelauncher-amazon/pom.xml
incubator/ace/trunk/ace-nodelauncher-amazon/src/
incubator/ace/trunk/ace-nodelauncher-amazon/src/main/
incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/
incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/
incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/
incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/
incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/
incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/
incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/Activator.java
incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/AmazonNodeLauncher.java
Modified:
incubator/ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncher.java
incubator/ace/trunk/pom.xml
incubator/ace/trunk/pom/pom.xml
Added: incubator/ace/trunk/ace-nodelauncher-amazon/pom.xml
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-nodelauncher-amazon/pom.xml?rev=1083544&view=auto
==============================================================================
--- incubator/ace/trunk/ace-nodelauncher-amazon/pom.xml (added)
+++ incubator/ace/trunk/ace-nodelauncher-amazon/pom.xml Sun Mar 20 19:23:04 2011
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.ace</groupId>
+ <artifactId>ace-pom</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ <relativePath>../pom/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>org.apache.ace.nodelauncher.amazon</artifactId>
+ <packaging>bundle</packaging>
+
+ <name>Apache ACE :: NodeLauncher :: Amazon provider</name>
+ <description></description>
+
+ <properties>
+ <private.package>
+ org.apache.ace.nodelauncher.amazon
+ </private.package>
+ <import.package>
+ !com.google.inject.internal.asm.util,
+ !junit.*,
+ !javax.mail.*,
+ !com.jamesmurty.utils,
+ !com.jcraft.jzlib,
+ !javax.swing*,
+ !sun.misc,
+ *
+ </import.package>
+ <bundle.activator>
+ org.apache.ace.nodelauncher.amazon.Activator
+ </bundle.activator>
+ <embed.dependency>jclouds-*, ec2, aws-common, aws-ec2, jsch</embed.dependency>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.dependencymanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ace</groupId>
+ <artifactId>org.apache.ace.nodelauncher.api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>1.0-beta-9b</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-blobstore</artifactId>
+ <version>1.0-beta-9b</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-compute</artifactId>
+ <version>1.0-beta-9b</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.common</groupId>
+ <artifactId>aws-common</artifactId>
+ <version>1.0-beta-9b</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.api</groupId>
+ <artifactId>ec2</artifactId>
+ <version>1.0-beta-9b</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.provider</groupId>
+ <artifactId>aws-ec2</artifactId>
+ <version>1.0-beta-9b</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-loadbalancer</artifactId>
+ <version>1.0-beta-9b</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-scriptbuilder</artifactId>
+ <version>1.0-beta-9b</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds.driver</groupId>
+ <artifactId>jclouds-jsch</artifactId>
+ <version>1.0-beta-9b</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.jcraft</groupId>
+ <artifactId>jsch</artifactId>
+ <version>0.1.44-1</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file
Added: incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/Activator.java?rev=1083544&view=auto
==============================================================================
--- incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/Activator.java
(added)
+++ incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/Activator.java
Sun Mar 20 19:23:04 2011
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.nodelauncher.amazon;
+
+import java.util.Properties;
+
+import org.apache.ace.nodelauncher.NodeLauncher;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.BundleContext;
+
+public class Activator extends DependencyActivatorBase {
+
+ @Override
+ public void init(BundleContext context, DependencyManager manager) throws Exception {
+ Properties props = new Properties();
+ props.put("osgi.command.scope", "node");
+ props.put("osgi.command.function", new String[] {"start", "stop", "properties"});
+ manager.add(createComponent()
+ .setInterface(NodeLauncher.class.getName(), props)
+ .setImplementation(AmazonNodeLauncher.class)
+ .add(createConfigurationDependency()
+ .setPid(AmazonNodeLauncher.PID)));
+ }
+
+ @Override
+ public void destroy(BundleContext context, DependencyManager manager) throws Exception
{
+
+ }
+
+}
Added: incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/AmazonNodeLauncher.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/AmazonNodeLauncher.java?rev=1083544&view=auto
==============================================================================
--- incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/AmazonNodeLauncher.java
(added)
+++ incubator/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/AmazonNodeLauncher.java
Sun Mar 20 19:23:04 2011
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.nodelauncher.amazon;
+
+import org.apache.ace.nodelauncher.NodeLauncher;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.ComputeServiceContextFactory;
+import org.jclouds.compute.domain.ComputeMetadata;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeState;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.options.RunScriptOptions;
+import org.jclouds.ec2.compute.options.EC2TemplateOptions;
+import org.jclouds.ec2.domain.InstanceType;
+import org.jclouds.ec2.reference.EC2Constants;
+import org.jclouds.scriptbuilder.domain.Statements;
+import org.jclouds.ssh.jsch.config.JschSshClientModule;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+import static org.jclouds.compute.predicates.NodePredicates.runningInGroup;
+
+/**
+ * Simple NodeLauncher implementation that launches nodes based on a given AMI in Amazon
EC2.
+ * We expect the AMI we launch to have a java on its path, at least after bootstrap.<br><br>
+ *
+ * This service is configured using Config Admin; see the constants in the class for more
information
+ * about this.<br><br>
+ *
+ * After the node has been started up, this service will install a management agent on it.
For this
+ * to work, there should be an ace-launcer in the OBR of the server the node should connect
to.
+ */
+public class AmazonNodeLauncher implements NodeLauncher, ManagedService {
+ public static final String PID = "org.apache.ace.nodelauncher.amazon";
+
+ /**
+ * Configuration key: The ACE server the newly started nodes should connect to.
+ */
+ public static final String SERVER = "server";
+
+ /**
+ * Configuration key: The ID of the AMI to use. Note that this AMI should be available
+ * in the location ("availability zone") you configure.
+ */
+ public static final String AMI_ID = "amiId";
+
+ /**
+ * Configuration key: The location where the node should be started; this is an Amazon
"availability zone",
+ * something like "eu-west-1".
+ */
+ public static final String LOCATION = "location";
+
+ /**
+ * Configuration key: the Amazon access key ID.
+ */
+ public static final String ACCESS_KEY_ID = "accessKeyid";
+
+ /**
+ * Configuration key: The secret key that goes with your access key.
+ */
+ public static final String SECRET_ACCESS_KEY = "secretAccessKey";
+
+ /**
+ * Configuration key: A prefix to use for all nodes launched by this service. You can
use this (a) allow
+ * multiple nodes with the same ID, but launcher from different NodeLauncher services,
or (b) to more
+ * easily identify your nodes in the AWS management console.
+ */
+ public static final String TAG_PREFIX = "tagPrefix";
+
+ /**
+ * Configuration key: A piece of shell script that is run <em>before</em>
the management agent is started.
+ */
+ public static final String NODE_BOOTSTRAP = "nodeBootstrap";
+
+ /**
+ * Configuration key: A set of VM options to pass to the JVM when starting the management
agent, as a single string.
+ */
+ public static final String VM_OPTIONS = "vmOptions";
+
+ /**
+ * Configuration key: Any command line arguments you want to pass to the launcher; see
the ace-launcher for
+ * the possible options.
+ */
+ public static final String LAUNCHER_ARGUMENTS = "launcherArguments";
+
+ private URL m_server;
+ private String m_amiId;
+ private String m_location;
+ private String m_accessKeyId;
+ private String m_secretAccessKey;
+ private String m_tagPrefix;
+ private String m_vmOptions;
+ private String m_nodeBootstrap;
+ private String m_launcherArguments;
+
+ private ComputeServiceContext m_computeServiceContext;
+
+ public void start() {
+ Properties props = new Properties();
+ props.put(EC2Constants.PROPERTY_EC2_AMI_OWNERS, "");
+ m_computeServiceContext = new ComputeServiceContextFactory().createContext("aws-ec2",
+ m_accessKeyId, m_secretAccessKey, (List) Arrays.asList(new JschSshClientModule()),
props);
+ }
+
+ public void start(String id) throws Exception {
+ ComputeService computeService = m_computeServiceContext.getComputeService();
+ Template template = computeService.templateBuilder()
+ .imageId(m_location + "/" + m_amiId)
+ .hardwareId(InstanceType.C1_MEDIUM)
+ .locationId(m_location)
+ .build();
+
+ template.getOptions().as(EC2TemplateOptions.class).inboundPorts(22, 80, 8080);
+ template.getOptions().blockOnComplete(false);
+
+ Set<? extends NodeMetadata> tag = computeService.createNodesInGroup(m_tagPrefix
+ id, 1, template);
+ System.out.println("In case you need it, this is the key to ssh to " + id + ":\n"
+ + tag.iterator().next().getCredentials().credential);
+ computeService.runScriptOnNodesMatching(runningInGroup(m_tagPrefix + id),
+ Statements.exec(buildStartupScript(id)),
+ RunScriptOptions.Builder.blockOnComplete(false));
+ }
+
+ private String buildStartupScript(String id) throws MalformedURLException {
+ StringBuilder script = new StringBuilder();
+ if (m_nodeBootstrap != null) {
+ script.append(m_nodeBootstrap).append(" ; ");
+ }
+ script.append("wget ").append(new URL(m_server, "/obr/ace-launcher.jar")).append("
;");
+
+ script.append("nohup java -Ddiscovery=").append(m_server.toExternalForm()).append("
");
+ script.append("-Didentification=").append(id).append(" ");
+ script.append(m_vmOptions).append(" ");
+ script.append("-jar ace-launcher.jar ");
+ script.append(m_launcherArguments);
+ return script.toString();
+ }
+
+ public void stop(String id) {
+ m_computeServiceContext.getComputeService().destroyNodesMatching(runningInGroup(m_tagPrefix
+ id));
+ }
+
+ public Properties getProperties(String id) throws Exception {
+ Properties result = new Properties();
+
+ NodeMetadata nodeMetadata = getNodeMetadataForRunningNodeWithTag(m_tagPrefix + id);
+ if (nodeMetadata == null) {
+ return null;
+ }
+ result.put("id", id);
+ result.put("node-id", nodeMetadata.getId());
+ result.put("ip", nodeMetadata.getPublicAddresses().iterator().next());
+
+ return result;
+ }
+
+ private NodeMetadata getNodeMetadataForRunningNodeWithTag(String tag) {
+ for (ComputeMetadata node : m_computeServiceContext.getComputeService().listNodes())
{
+ NodeMetadata candidate = m_computeServiceContext.getComputeService().getNodeMetadata(node.getId());
+ if (candidate.getGroup().equals(tag) && candidate.getState().equals(NodeState.RUNNING))
{
+ return candidate;
+ }
+ }
+ return null;
+ }
+
+ public void updated(@SuppressWarnings("rawtypes") Dictionary properties) throws ConfigurationException
{
+ if (properties != null) {
+ URL server;
+ try {
+ server = new URL(getConfigProperty(properties, SERVER));
+ }
+ catch (MalformedURLException e) {
+ throw new ConfigurationException(SERVER, getConfigProperty(properties, SERVER)
+ " is not a valid URL.", e);
+ }
+ String amiId = getConfigProperty(properties, AMI_ID);
+ String location = getConfigProperty(properties, LOCATION);
+ String accessKeyId = getConfigProperty(properties, ACCESS_KEY_ID);
+ String secretAccessKey = getConfigProperty(properties, SECRET_ACCESS_KEY);
+
+ String vmOptions = getConfigProperty(properties, VM_OPTIONS, "");
+ String nodeBootstrap = getConfigProperty(properties, NODE_BOOTSTRAP, "");
+ String tagPrefix = getConfigProperty(properties, TAG_PREFIX, "");
+ String launcherArguments = getConfigProperty(properties, LAUNCHER_ARGUMENTS,
"");
+
+ m_server = server;
+ m_amiId = amiId;
+ m_location = location;
+ m_accessKeyId = accessKeyId;
+ m_secretAccessKey = secretAccessKey;
+ m_tagPrefix = tagPrefix;
+ m_vmOptions = vmOptions;
+ m_nodeBootstrap = nodeBootstrap;
+ m_launcherArguments = launcherArguments;
+ }
+ }
+
+ private String getConfigProperty(@SuppressWarnings("rawtypes") Dictionary settings, String
id)
+ throws ConfigurationException {
+ return getConfigProperty(settings, id, null);
+ }
+
+ private String getConfigProperty(@SuppressWarnings("rawtypes") Dictionary settings, String
id, String defaultValue)
+ throws ConfigurationException {
+ String result = (String) settings.get(id);
+ if (result == null) {
+ if (defaultValue == null) {
+ throw new ConfigurationException(id, "key missing");
+ }
+ else {
+ return defaultValue;
+ }
+ }
+ return result;
+ }
+}
Modified: incubator/ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncher.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncher.java?rev=1083544&r1=1083543&r2=1083544&view=diff
==============================================================================
--- incubator/ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncher.java
(original)
+++ incubator/ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncher.java
Sun Mar 20 19:23:04 2011
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
package org.apache.ace.nodelauncher;
import java.util.Properties;
Modified: incubator/ace/trunk/pom.xml
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/pom.xml?rev=1083544&r1=1083543&r2=1083544&view=diff
==============================================================================
--- incubator/ace/trunk/pom.xml (original)
+++ incubator/ace/trunk/pom.xml Sun Mar 20 19:23:04 2011
@@ -115,6 +115,7 @@
<module>ace-target-devserver</module>
<module>ace-nodelauncher-api</module>
+ <module>ace-nodelauncher-amazon</module>
<!-- not ready yet
<module>ace-distribution-servlet</module>
Modified: incubator/ace/trunk/pom/pom.xml
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/pom/pom.xml?rev=1083544&r1=1083543&r2=1083544&view=diff
==============================================================================
--- incubator/ace/trunk/pom/pom.xml (original)
+++ incubator/ace/trunk/pom/pom.xml Sun Mar 20 19:23:04 2011
@@ -568,6 +568,11 @@
</dependency>
<dependency>
<groupId>org.apache.ace</groupId>
+ <artifactId>org.apache.ace.nodelauncher.api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ace</groupId>
<artifactId>org.apache.ace.webui</artifactId>
<version>${project.version}</version>
<type>war</type>
|