Author: paulb
Date: Sun Jun 10 09:56:35 2012
New Revision: 1348558
URL: http://svn.apache.org/viewvc?rev=1348558&view=rev
Log:
ACE-277 Cloud nodes can now be configured from the UI.
Added:
ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/JcloudsNodeLauncherConfig.java
ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncherConfig.java
Modified:
ace/trunk/ace-nodelauncher-amazon/pom.xml
ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/AmazonNodeLauncher.java
ace/trunk/ace-nodelauncher-amazon/src/test/java/org/apache/ace/nodelauncher/amazon/PortParseTest.java
ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncher.java
ace/trunk/ace-nodelauncher-ui/pom.xml
ace/trunk/ace-nodelauncher-ui/src/main/java/org/apache/ace/nodelauncher/ui/NodePanel.java
Modified: ace/trunk/ace-nodelauncher-amazon/pom.xml
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-nodelauncher-amazon/pom.xml?rev=1348558&r1=1348557&r2=1348558&view=diff
==============================================================================
--- ace/trunk/ace-nodelauncher-amazon/pom.xml (original)
+++ ace/trunk/ace-nodelauncher-amazon/pom.xml Sun Jun 10 09:56:35 2012
@@ -67,6 +67,10 @@
</bundle.activator>
<embed.dependency>*;scope=compile;groupId=!org.osgi|org.apache.felix|org.apache.ace</embed.dependency>
<embed.transitive>true</embed.transitive>
+ <export.package>
+ org.apache.ace.nodelauncher.amazon;version=${project.version},
+ org.jclouds.compute.domain
+ </export.package>
</properties>
<dependencies>
Modified:
ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/AmazonNodeLauncher.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/AmazonNodeLauncher.java?rev=1348558&r1=1348557&r2=1348558&view=diff
==============================================================================
---
ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/AmazonNodeLauncher.java
(original)
+++
ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/AmazonNodeLauncher.java
Sun Jun 10 09:56:35 2012
@@ -18,23 +18,20 @@
*/
package org.apache.ace.nodelauncher.amazon;
-import com.google.common.collect.ImmutableSet;
import com.google.common.io.Files;
-import com.google.inject.Module;
import org.apache.ace.nodelauncher.NodeLauncher;
+import org.apache.ace.nodelauncher.NodeLauncherConfig;
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.domain.TemplateBuilder;
import org.jclouds.compute.options.RunScriptOptions;
-import org.jclouds.domain.Credentials;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.LoginCredentials;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.InstanceType;
import org.jclouds.scriptbuilder.domain.Statements;
-import org.jclouds.sshj.config.SshjSshClientModule;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
@@ -42,10 +39,11 @@ import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
-import java.util.*;
+import java.util.Dictionary;
+import java.util.Properties;
+import java.util.Set;
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>
@@ -71,6 +69,11 @@ public class AmazonNodeLauncher implemen
public static final String AMI_ID = "amiId";
/**
+ * Configuration key: The ID of the AMI owner to use. You need this when
you want to use your own AMIs.
+ */
+ public static final String AMI_OWNER_ID = "amiOwnerId";
+
+ /**
* Configuration key: The location where the node should be started; this
is an Amazon "availability zone",
* something like "eu-west-1".
*/
@@ -134,7 +137,7 @@ public class AmazonNodeLauncher implemen
/**
* Default set of ports to open on a node.
*/
- public static final int[] DEFAULT_PORTS = new int[] {22, 80, 8080};
+ public static final int[] DEFAULT_PORTS = new int[]{22, 80, 8080};
/**
* Configuration key: The (optional) name of the JAR to launch to
@@ -154,69 +157,88 @@ public class AmazonNodeLauncher implemen
* bootstrapping.
*/
public static final String EXTERNAL_DOWNLOAD_URLS = "externalDownloadUrls";
-
+
+ /**
+ * Configuration key: The (optional) ssh user to use when connecting to
the node. Uses jclouds defaults by default,
+ * which is root and ec2-user.
+ */
+ public static final String SSH_USER = "sshUser";
+
/**
* Configuration key: The (optional) private key file, which you must
install on
* the ACE server locally if you want it to be used when creating new
nodes.
*/
private static final String PRIVATE_KEY_FILE = "privateKeyFile";
- private URL m_server;
- private String m_amiId;
- private String m_location;
- private String m_hardwareId;
- private String m_accessKeyId;
- private String m_secretAccessKey;
- private String m_keypair;
- private String m_privateKeyFile;
- private String m_tagPrefix;
- private String m_vmOptions;
- private String m_nodeBootstrap;
- private String m_launcherArguments;
- private String m_extraPorts;
- private boolean m_runAsRoot;
- private String m_aceLauncher;
- private String m_additionalObrDownloads;
- private String m_externalDownloadUrls;
-
-
- private ComputeServiceContext m_computeServiceContext;
-
- public void start() {
- Properties props = new Properties();
- m_computeServiceContext = new
ComputeServiceContextFactory().createContext("aws-ec2", m_accessKeyId,
m_secretAccessKey, ImmutableSet.<Module> of(new SshjSshClientModule()), props);
- }
+ /**
+ * Default configuration object. Properties are read from the nodelauncher
configuration file.
+ */
+ private JcloudsNodeLauncherConfig m_defaultNodeConfig;
+
+ /**
+ * Current configuration object. This reflects settings done from the UI
for example.
+ * This instance is set when a node is started.
+ */
+ private JcloudsNodeLauncherConfig m_currentConfig;
+
public void start(String id) throws Exception {
- ComputeService computeService =
m_computeServiceContext.getComputeService();
- Template template = computeService.templateBuilder()
- .imageId(m_location + "/" + m_amiId)
- .hardwareId(m_hardwareId)
- .locationId(m_location)
- .build();
- int[] extraPorts = parseExtraPorts(m_extraPorts);
+ start(id, m_defaultNodeConfig);
+ }
+
+ public void start(String id, NodeLauncherConfig cfg) throws Exception {
+ JcloudsNodeLauncherConfig config = (JcloudsNodeLauncherConfig) cfg;
+ m_currentConfig = config;
+
+ ComputeService computeService = config.getComputeService();
+ TemplateBuilder template = computeService.templateBuilder()
+ .imageId(config.getImageId())
+ .hardwareId(config.getHardwareId())
+ .locationId(config.getLocation());
+
+ int[] extraPorts = parseExtraPorts(config.getExtraPorts());
int[] inboundPorts = mergePorts(DEFAULT_PORTS, extraPorts);
-
template.getOptions().as(EC2TemplateOptions.class).inboundPorts(inboundPorts);
- template.getOptions().blockOnComplete(false);
- template.getOptions().runAsRoot(m_runAsRoot);
- if (useConfiguredKeyPair()) {
-
template.getOptions().as(EC2TemplateOptions.class).keyPair(m_keypair);
- template.getOptions().overrideCredentialsWith(new
Credentials("ec2-user", Files.toString(new File(m_privateKeyFile),
Charset.defaultCharset())));
+ TemplateOptions options = new EC2TemplateOptions()
+ .as(EC2TemplateOptions.class).inboundPorts(inboundPorts)
+ .blockOnComplete(false)
+ .runAsRoot(config.isRunAsRoot());
+
+ if (useConfiguredKeyPair(config)) {
+ options.as(EC2TemplateOptions.class).keyPair(config.getKeyPair());
}
- Set<? extends NodeMetadata> tag =
computeService.createNodesInGroup(m_tagPrefix + id, 1, template);
- if (!useConfiguredKeyPair()) {
+ template.options(options);
+
+ Set<? extends NodeMetadata> tag =
computeService.createNodesInGroup(config.getTagPrefix() + id, 1,
template.build());
+ if (!useConfiguredPrivateKey(config)) {
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));
+
+ LoginCredentials.Builder loginBuilder = LoginCredentials.builder();
+
+ if (config.getSshUser() != null && config.getSshUser().length() > 0) {
+ loginBuilder.user(config.getSshUser());
+ } else {
+ loginBuilder.user("ec2-user");
+ }
+
+ if (useConfiguredPrivateKey(config)) {
+ loginBuilder.privateKey(Files.toString(new
File(config.getPrivateKeyFile()), Charset.defaultCharset()));
+ }
+
+
computeService.runScriptOnNodesMatching(runningInGroup(config.getTagPrefix() +
id),
+ Statements.exec(buildStartupScript(id, config)),
+
RunScriptOptions.Builder.blockOnComplete(false).overrideLoginCredentials(loginBuilder.build()));
}
- private boolean useConfiguredKeyPair() {
- return m_keypair != null && m_keypair.length() > 0;
+ private boolean useConfiguredPrivateKey(JcloudsNodeLauncherConfig config) {
+ return config.getPrivateKeyFile() != null &&
config.getPrivateKeyFile().length() > 0;
+ }
+
+ private boolean useConfiguredKeyPair(JcloudsNodeLauncherConfig config) {
+ return config.getKeyPair() != null && config.getKeyPair().length() > 0;
}
int[] mergePorts(int[] first, int[] last) {
@@ -227,53 +249,56 @@ public class AmazonNodeLauncher implemen
return result;
}
- int[] parseExtraPorts(String extraPorts) {
- extraPorts = extraPorts.trim();
- if (extraPorts.isEmpty()) {
- return new int[]{};
- }
- String[] ports = extraPorts.split(",");
- int[] result = new int[ports.length];
- for (int i = 0; i < ports.length; i++) {
- result[i] = Integer.parseInt(ports[i].trim());
+ int[] parseExtraPorts(String[] extraPorts) {
+ if(extraPorts == null || extraPorts.length == 0) {
+ return new int[0];
+ }
+
+ int[] result = new int[extraPorts.length];
+
+ for (int i = 0; i < extraPorts.length; i++) {
+ result[i] = Integer.parseInt(extraPorts[i].trim());
}
+
return result;
}
- private String buildStartupScript(String id) throws MalformedURLException {
- StringBuilder script = new StringBuilder();
- if (m_nodeBootstrap != null && m_nodeBootstrap.length() > 0) {
- script.append(m_nodeBootstrap).append(" ; ");
+ private String buildStartupScript(String id, JcloudsNodeLauncherConfig
config) throws MalformedURLException {
+ StringBuilder script = new StringBuilder("cd ~; ");
+ if (config.getNodeBootstrap() != null &&
config.getNodeBootstrap().length() > 0) {
+ script.append(config.getNodeBootstrap()).append(" ; ");
}
- script.append("wget ").append(new URL(m_server, "/obr/" +
m_aceLauncher)).append(" ;");
- if (m_additionalObrDownloads.length() > 0) {
- for (String additonalDownload :
m_additionalObrDownloads.split(",")) {
- script.append("wget ").append(new URL(m_server, "/obr/" +
additonalDownload.trim())).append(" ;");
+ script.append("wget ").append(new URL(config.getServer(), "/obr/" +
config.getAceLauncher())).append(" ;");
+ if (config.getAdditionalObrDownloads().length() > 0) {
+ for (String additonalDownload :
config.getAdditionalObrDownloads().split(",")) {
+ script.append("wget ").append(new URL(config.getServer(),
"/obr/" + additonalDownload.trim())).append(" ;");
}
}
- if (m_externalDownloadUrls.length() > 0) {
- for (String additonalDownload : m_externalDownloadUrls.split(","))
{
+ if (config.getExternalDownloadUrls().length() > 0) {
+ for (String additonalDownload :
config.getExternalDownloadUrls().split(",")) {
script.append("wget
").append(additonalDownload.trim()).append(" ;");
}
}
- script.append("nohup java -jar ").append(m_aceLauncher).append(" ");
- script.append("discovery=").append(m_server.toExternalForm()).append("
");
+ script.append("nohup java -jar
").append(config.getAceLauncher()).append(" ");
+
script.append("discovery=").append(config.getServer().toExternalForm()).append("
");
script.append("identification=").append(id).append(" ");
- script.append(m_vmOptions).append(" ");
- script.append(m_launcherArguments);
+ script.append(config.getVmOptions()).append(" ");
+ script.append(config.getLauncherArguments());
return script.toString();
}
public void stop(String id) {
-
m_computeServiceContext.getComputeService().destroyNodesMatching(runningInGroup(m_tagPrefix
+ id));
+
+
getActiveConfig().getComputeService().destroyNodesMatching(runningInGroup(getActiveConfig().getTagPrefix()
+ id));
}
public Properties getProperties(String id) throws Exception {
Properties result = new Properties();
- NodeMetadata nodeMetadata =
getNodeMetadataForRunningNodeWithTag(m_tagPrefix + id);
+ JcloudsNodeLauncherConfig config = getActiveConfig();
+ NodeMetadata nodeMetadata =
getNodeMetadataForRunningNodeWithTag(config.getTagPrefix() + id, config);
if (nodeMetadata == null) {
return null;
}
@@ -284,9 +309,14 @@ public class AmazonNodeLauncher implemen
return result;
}
- private NodeMetadata getNodeMetadataForRunningNodeWithTag(String tag) {
- for (ComputeMetadata node :
m_computeServiceContext.getComputeService().listNodes()) {
- NodeMetadata candidate =
m_computeServiceContext.getComputeService().getNodeMetadata(node.getId());
+ private JcloudsNodeLauncherConfig getActiveConfig() {
+ return m_currentConfig != null ? m_currentConfig : m_defaultNodeConfig;
+ }
+
+ private NodeMetadata getNodeMetadataForRunningNodeWithTag(String tag,
JcloudsNodeLauncherConfig config) {
+
+ for (ComputeMetadata node : config.getComputeService().listNodes()) {
+ NodeMetadata candidate =
config.getComputeService().getNodeMetadata(node.getId());
if (tag.equals(candidate.getGroup()) &&
candidate.getState().equals(NodeState.RUNNING)) {
return candidate;
}
@@ -299,11 +329,11 @@ public class AmazonNodeLauncher implemen
URL server;
try {
server = new URL(getConfigProperty(properties, SERVER));
- }
- catch (MalformedURLException e) {
+ } catch (MalformedURLException e) {
throw new ConfigurationException(SERVER,
getConfigProperty(properties, SERVER) + " is not a valid URL.", e);
}
String amiId = getConfigProperty(properties, AMI_ID);
+ String amiOwnerId = getConfigProperty(properties, AMI_OWNER_ID,
"");
String location = getConfigProperty(properties, LOCATION);
String hardwareId = getConfigProperty(properties, HARDWARE_ID,
InstanceType.C1_MEDIUM);
String accessKeyId = getConfigProperty(properties, ACCESS_KEY_ID);
@@ -319,27 +349,36 @@ public class AmazonNodeLauncher implemen
String aceLauncher = getConfigProperty(properties, ACE_LAUNCHER,
"ace-launcher.jar");
String additionalObrDownloads = getConfigProperty(properties,
ADDITIONAL_OBR_DOWNLOADS, "");
String externalDownloadUrls = getConfigProperty(properties,
EXTERNAL_DOWNLOAD_URLS, "");
+ String sshUser = getConfigProperty(properties, SSH_USER,
"ec2-user");
+
+ m_defaultNodeConfig = new JcloudsNodeLauncherConfig()
+ .setAccessKeyId(accessKeyId)
+ .setSecretAccessKey(secretAccessKey)
+ .setServer(server)
+ .setImageId(amiId)
+ .setImageOwnerId(amiOwnerId)
+ .setLocation(location)
+ .setHardwareId(hardwareId)
+ .setKeyPair(keyPair)
+ .setPrivateKeyFile(privateKeyFile)
+ .setTagPrefix(tagPrefix)
+ .setVmOptions(vmOptions)
+ .setLauncherArguments(launcherArguments)
+ .setExtraPorts(extraPorts)
+ .setRunAsRoot(Boolean.parseBoolean(runAsRoot))
+ .setAccessKeyId(accessKeyId)
+ .setSecretAccessKey(secretAccessKey)
+ .setNodeBootstrap(nodeBootstrap)
+ .setAceLauncher(aceLauncher)
+ .setAdditionalObrDownloads(additionalObrDownloads)
+ .setExternalDownloadUrls(externalDownloadUrls)
+ .setSshUser(sshUser);
- m_server = server;
- m_amiId = amiId;
- m_location = location;
- m_hardwareId = hardwareId;
- m_accessKeyId = accessKeyId;
- m_secretAccessKey = secretAccessKey;
- m_keypair = keyPair;
- m_privateKeyFile = privateKeyFile;
- m_tagPrefix = tagPrefix;
- m_vmOptions = vmOptions;
- m_nodeBootstrap = nodeBootstrap;
- m_launcherArguments = launcherArguments;
- m_extraPorts = extraPorts;
- m_runAsRoot = "true".equals(runAsRoot);
- m_aceLauncher = aceLauncher;
- m_additionalObrDownloads = additionalObrDownloads;
- m_externalDownloadUrls = externalDownloadUrls;
+ m_defaultNodeConfig.createComputeServiceContext();
}
}
+
private String getConfigProperty(@SuppressWarnings("rawtypes") Dictionary
settings, String id) throws ConfigurationException {
return getConfigProperty(settings, id, null);
}
@@ -349,11 +388,24 @@ public class AmazonNodeLauncher implemen
if (result == null) {
if (defaultValue == null) {
throw new ConfigurationException(id, "key missing");
- }
- else {
+ } else {
return defaultValue;
}
}
return result;
}
+
+ public void stop() {
+ if (m_currentConfig != null) {
+ m_currentConfig.close();
+ }
+ }
+
+ public NodeLauncherConfig getDefaultConfig() {
+ return m_defaultNodeConfig;
+ }
+
+ public JcloudsNodeLauncherConfig getCurrentConfig() {
+ return m_currentConfig;
+ }
}
Added:
ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/JcloudsNodeLauncherConfig.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/JcloudsNodeLauncherConfig.java?rev=1348558&view=auto
==============================================================================
---
ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/JcloudsNodeLauncherConfig.java
(added)
+++
ace/trunk/ace-nodelauncher-amazon/src/main/java/org/apache/ace/nodelauncher/amazon/JcloudsNodeLauncherConfig.java
Sun Jun 10 09:56:35 2012
@@ -0,0 +1,269 @@
+/*
+ * 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 com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+import org.apache.ace.nodelauncher.NodeLauncherConfig;
+import org.jclouds.aws.ec2.reference.AWSEC2Constants;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.ComputeServiceContextFactory;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.sshj.config.SshjSshClientModule;
+
+import java.net.URL;
+import java.util.Properties;
+import java.util.Set;
+
+public class JcloudsNodeLauncherConfig implements NodeLauncherConfig {
+ private ComputeServiceContext m_computeServiceContext;
+
+ private URL m_server;
+ private String m_hardwareId;
+ private String m_ImageId;
+ private String m_ImageOwnerId;
+ private String m_location;
+ private String m_tagPrefix;
+ private String[] m_extraPorts;
+ private boolean m_runAsRoot;
+ private String m_keyPair;
+ private String m_privateKeyFile;
+ private String m_vmOptions;
+ private String m_launcherArguments;
+
+ private String m_accessKeyId;
+ private String m_secretAccessKey;
+
+ private String m_nodeBootstrap;
+ private String m_aceLauncher;
+ private String m_additionalObrDownloads;
+ private String m_externalDownloadUrls;
+ private String m_sshUser;
+
+ public URL getServer() {
+ return m_server;
+ }
+
+ public JcloudsNodeLauncherConfig setServer(URL server) {
+ m_server = server;
+ return this;
+ }
+
+ public String getHardwareId() {
+ return m_hardwareId;
+ }
+
+ public JcloudsNodeLauncherConfig setHardwareId(String hardwareId) {
+ m_hardwareId = hardwareId;
+ return this;
+ }
+
+ public String getImageId() {
+ return m_ImageId;
+ }
+
+ public JcloudsNodeLauncherConfig setImageId(String m_ImageId) {
+ this.m_ImageId = m_ImageId;
+ return this;
+ }
+
+ public String getImageOwnerId() {
+ return m_ImageOwnerId;
+ }
+
+ public String getTagPrefix() {
+ return m_tagPrefix;
+ }
+
+ public JcloudsNodeLauncherConfig setTagPrefix(String tagPrefix) {
+ this.m_tagPrefix = tagPrefix;
+ return this;
+ }
+
+ public String getLocation() {
+ return m_location;
+ }
+
+ public JcloudsNodeLauncherConfig setLocation(String location) {
+ m_location = location;
+ return this;
+ }
+
+ public String[] getExtraPorts() {
+ return m_extraPorts;
+ }
+
+ public JcloudsNodeLauncherConfig setExtraPorts(String... extraPorts) {
+ m_extraPorts = extraPorts;
+ return this;
+ }
+
+ public boolean isRunAsRoot() {
+ return m_runAsRoot;
+ }
+
+ public JcloudsNodeLauncherConfig setRunAsRoot(boolean runAsRoot) {
+ m_runAsRoot = runAsRoot;
+ return this;
+ }
+
+ public String getKeyPair() {
+ return m_keyPair;
+ }
+
+ public JcloudsNodeLauncherConfig setKeyPair(String keyPair) {
+ m_keyPair = keyPair;
+ return this;
+ }
+
+ public String getPrivateKeyFile() {
+ return m_privateKeyFile;
+ }
+
+ public JcloudsNodeLauncherConfig setPrivateKeyFile(String privateKeyFile) {
+ m_privateKeyFile = privateKeyFile;
+ return this;
+ }
+
+ public String getVmOptions() {
+ return m_vmOptions;
+ }
+
+ public JcloudsNodeLauncherConfig setVmOptions(String vmOptions) {
+ m_vmOptions = vmOptions;
+ return this;
+ }
+
+ public String getLauncherArguments() {
+ return m_launcherArguments;
+ }
+
+ public JcloudsNodeLauncherConfig setLauncherArguments(String
launcherArguments) {
+ m_launcherArguments = launcherArguments;
+ return this;
+ }
+
+ public Set<? extends Hardware> listHardwareIds() {
+ return
m_computeServiceContext.getComputeService().listHardwareProfiles();
+ }
+
+ public Set<? extends Image> listImages() {
+ return m_computeServiceContext.getComputeService().listImages();
+ }
+
+ public JcloudsNodeLauncherConfig setImageOwnerId(String imageOwnerId) {
+ m_ImageOwnerId = imageOwnerId;
+ createComputeServiceContext();
+
+ return this;
+ }
+
+ public String getAccessKeyId() {
+ return m_accessKeyId;
+ }
+
+ public JcloudsNodeLauncherConfig setAccessKeyId(String accessKeyId) {
+ m_accessKeyId = accessKeyId;
+ return this;
+ }
+
+ public String getSecretAccessKey() {
+ return m_secretAccessKey;
+ }
+
+ public JcloudsNodeLauncherConfig setSecretAccessKey(String
secretAccessKey) {
+ m_secretAccessKey = secretAccessKey;
+ return this;
+ }
+
+ public String getNodeBootstrap() {
+ return m_nodeBootstrap;
+ }
+
+ public JcloudsNodeLauncherConfig setNodeBootstrap(String nodeBootstrap) {
+ m_nodeBootstrap = nodeBootstrap;
+ return this;
+ }
+
+ public String getAceLauncher() {
+ return m_aceLauncher;
+ }
+
+ public JcloudsNodeLauncherConfig setAceLauncher(String aceLauncher) {
+ m_aceLauncher = aceLauncher;
+ return this;
+ }
+
+ public String getAdditionalObrDownloads() {
+ return m_additionalObrDownloads;
+ }
+
+ public JcloudsNodeLauncherConfig setAdditionalObrDownloads(String
additionalObrDownloads) {
+ m_additionalObrDownloads = additionalObrDownloads;
+ return this;
+ }
+
+ public String getExternalDownloadUrls() {
+ return m_externalDownloadUrls;
+ }
+
+ public JcloudsNodeLauncherConfig setExternalDownloadUrls(String
externalDownloadUrls) {
+ m_externalDownloadUrls = externalDownloadUrls;
+ return this;
+ }
+
+ public String getSshUser() {
+ return m_sshUser;
+ }
+
+ public JcloudsNodeLauncherConfig setSshUser(String sshUser) {
+ this.m_sshUser = sshUser;
+ return this;
+ }
+
+ /**
+ * Recreate the ComputeServiceContext. This is required after setting some
properties to have an effect (e.g. changing ImageOwnerId).
+ * This is an expensive operation, only call when required.
+ */
+ public void createComputeServiceContext() {
+ if (m_computeServiceContext != null) {
+ m_computeServiceContext.close();
+ }
+
+ Properties props = new Properties();
+ if (m_ImageOwnerId != null && m_ImageOwnerId.length() > 0) {
+ props.setProperty(AWSEC2Constants.PROPERTY_EC2_AMI_QUERY,
"owner-id=" + m_ImageOwnerId +
";state=available;image-type=machine;root-device-type=ebs");
+ props.setProperty(AWSEC2Constants.PROPERTY_EC2_CC_AMI_QUERY, "");
+ }
+
+ m_computeServiceContext = new
ComputeServiceContextFactory().createContext("aws-ec2", m_accessKeyId,
m_secretAccessKey, ImmutableSet.<Module>of(new SshjSshClientModule()), props);
+ }
+
+ public ComputeService getComputeService() {
+ return m_computeServiceContext.getComputeService();
+ }
+
+ public void close() {
+ if(m_computeServiceContext != null) {
+ m_computeServiceContext.close();
+ }
+ }
+}
Modified:
ace/trunk/ace-nodelauncher-amazon/src/test/java/org/apache/ace/nodelauncher/amazon/PortParseTest.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-nodelauncher-amazon/src/test/java/org/apache/ace/nodelauncher/amazon/PortParseTest.java?rev=1348558&r1=1348557&r2=1348558&view=diff
==============================================================================
---
ace/trunk/ace-nodelauncher-amazon/src/test/java/org/apache/ace/nodelauncher/amazon/PortParseTest.java
(original)
+++
ace/trunk/ace-nodelauncher-amazon/src/test/java/org/apache/ace/nodelauncher/amazon/PortParseTest.java
Sun Jun 10 09:56:35 2012
@@ -8,10 +8,9 @@ public class PortParseTest {
@Test(groups = { UNIT })
public void testParsePortsFromString() throws Exception {
AmazonNodeLauncher instance = new AmazonNodeLauncher();
- Assert.assertTrue(assertEquals(instance.parseExtraPorts("1,2,3"), new
int[] {1, 2, 3}));
- Assert.assertTrue(assertEquals(instance.parseExtraPorts(""), new int[]
{}));
- Assert.assertTrue(assertEquals(instance.parseExtraPorts("1 ,2 , 3 "),
new int[] {1, 2, 3}));
- Assert.assertTrue(assertEquals(instance.parseExtraPorts("800,900"),
new int[] {800, 900}));
+ Assert.assertTrue(assertEquals(instance.parseExtraPorts(new String[]
{"1", "2", "3"}), new int[] {1, 2, 3}));
+ Assert.assertTrue(assertEquals(instance.parseExtraPorts(new String[]
{}), new int[] {}));
+ Assert.assertTrue(assertEquals(instance.parseExtraPorts(new String[]
{"800","900"}), new int[] {800, 900}));
}
@Test(groups = { UNIT })
Modified:
ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncher.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncher.java?rev=1348558&r1=1348557&r2=1348558&view=diff
==============================================================================
---
ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncher.java
(original)
+++
ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncher.java
Sun Jun 10 09:56:35 2012
@@ -38,11 +38,32 @@ public interface NodeLauncher {
void start(String id) throws Exception;
/**
+ * Starts a new node with the given ID. Does not check whether this ID is
already in use.
+ * The provided properties override the configuration provided in
configuration. Depending on the underlying
+ * provider this could be used to specify a node type, image id etc.
+ * @param id A textual ID for the node.
+ * @param config Configuration object to override configuration properties
such as node type.
+ * @throws Exception Be aware that the implementation may pass through
implementation-specific exceptions.
+ */
+ void start(String id, NodeLauncherConfig config) throws Exception;
+
+ /**
* Destroys the node with the given ID. Does not check whether this ID
actually exists.
* @param id A textual ID for the node.
* @throws Exception Be aware that the implementation may pass through
implementation-specific exceptions.
*/
void stop(String id) throws Exception;
+
+ /**
+ * If available, return a default configuration object. May return null if
not available in an implementation.
+ * @return Default launcher configuration, or null if not available.
+ */
+ NodeLauncherConfig getDefaultConfig();
+
+ /**
+ * @return The currently set configuration object if available, or null
if not available.
+ */
+ NodeLauncherConfig getCurrentConfig();
/**
* Retrieves properties from the node. These will include, at least
Added:
ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncherConfig.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncherConfig.java?rev=1348558&view=auto
==============================================================================
---
ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncherConfig.java
(added)
+++
ace/trunk/ace-nodelauncher-api/src/main/java/org/apache/ace/nodelauncher/NodeLauncherConfig.java
Sun Jun 10 09:56:35 2012
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+/**
+ * Empty interface that should be implemented by NodeLauncherConfig
implmentation. The interface is empty
+ * because configuration is very different for each kind of node (e.g. an
embedded node vs a jclouds node) it's
+ * not possible to have a standard interface for configuration.
+ * The interface is required however so that the NodeLauncherConfig can still
be independent of specific node types.
+ * Clients of this interface (e.g. UI) should cast this interface to the
concrete implementation it's built for.
+ *
+ */
+public interface NodeLauncherConfig {
+
+}
Modified: ace/trunk/ace-nodelauncher-ui/pom.xml
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-nodelauncher-ui/pom.xml?rev=1348558&r1=1348557&r2=1348558&view=diff
==============================================================================
--- ace/trunk/ace-nodelauncher-ui/pom.xml (original)
+++ ace/trunk/ace-nodelauncher-ui/pom.xml Sun Jun 10 09:56:35 2012
@@ -65,7 +65,7 @@
</dependency>
<dependency>
<groupId>org.apache.ace</groupId>
- <artifactId>org.apache.ace.nodelauncher.api</artifactId>
+ <artifactId>org.apache.ace.nodelauncher.amazon</artifactId>
</dependency>
<dependency>
<groupId>org.apache.ace</groupId>
Modified:
ace/trunk/ace-nodelauncher-ui/src/main/java/org/apache/ace/nodelauncher/ui/NodePanel.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-nodelauncher-ui/src/main/java/org/apache/ace/nodelauncher/ui/NodePanel.java?rev=1348558&r1=1348557&r2=1348558&view=diff
==============================================================================
---
ace/trunk/ace-nodelauncher-ui/src/main/java/org/apache/ace/nodelauncher/ui/NodePanel.java
(original)
+++
ace/trunk/ace-nodelauncher-ui/src/main/java/org/apache/ace/nodelauncher/ui/NodePanel.java
Sun Jun 10 09:56:35 2012
@@ -18,16 +18,19 @@
*/
package org.apache.ace.nodelauncher.ui;
+import com.vaadin.data.Property;
+import com.vaadin.ui.*;
+import com.vaadin.ui.Button.ClickListener;
+import org.apache.ace.nodelauncher.amazon.JcloudsNodeLauncherConfig;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.osgi.service.log.LogService;
+
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import com.vaadin.ui.*;
-import org.osgi.service.log.LogService;
-
-import com.vaadin.ui.Button.ClickListener;
-
@SuppressWarnings("serial")
public class NodePanel extends Panel {
private final String m_targetId;
@@ -36,7 +39,25 @@ public class NodePanel extends Panel {
private final NodeLauncherPanelFactory m_factory;
private final Map<Action, Runnable> m_runners = new HashMap<Action,
Runnable>();
private final Runnable m_statusGetter = new StatusGetter();
-
+ private TextField m_locationInput;
+ private Select m_hardwareIdSelect;
+ private TextField m_ImageOwnerIdInput;
+ private Select m_ImageIdSelect;
+ private TextField m_keyPairInput;
+ private TextField m_tagPrefixInput;
+ private TextField m_extraPortsInput;
+ private CheckBox m_runAsRootCheckbox;
+ private TextField m_privateKeyFileInput;
+ private TextField m_vmOptionsInput;
+ private TextField m_launcherArgumentsInput;
+ private TextField m_nodeBootstrapInput;
+ private TextField m_aceLauncherInput;
+ private TextField m_additionalObrDownloadsInput;
+ private TextField m_externalDownloadsInput;
+ private TextField m_sshUserInput;
+
+ private JcloudsNodeLauncherConfig config;
+
{
m_runners.put(Action.Start, new StartRunner());
m_runners.put(Action.Stop, new StopRunner());
@@ -45,6 +66,7 @@ public class NodePanel extends Panel {
public NodePanel(NodeLauncherPanelFactory factory, String target) {
m_factory = factory;
m_targetId = target;
+ config =
(JcloudsNodeLauncherConfig)m_factory.getCloudService().getDefaultConfig();
setContent();
setCaption(m_targetId);
}
@@ -64,17 +86,108 @@ public class NodePanel extends Panel {
buttonPanel.addComponent(startButton);
buttonPanel.addComponent(stopButton);
buttonPanel.setSpacing(true);
+
Table propertiesTable = new PropertiesTable(m_handler);
propertiesTable.setWidth("100%");
panel.addComponent(status);
panel.addComponent(buttonPanel);
+
+ m_locationInput = new TextField("Location", config.getLocation());
+ panel.addComponent(m_locationInput);
+
+ Set<? extends Hardware> hardwares = config.listHardwareIds();
+
+ m_hardwareIdSelect = new Select("Node type");
+ createHardwareItems(hardwares);
+ panel.addComponent(m_hardwareIdSelect);
+
+ m_ImageOwnerIdInput = new TextField("Image owner ID",
config.getImageOwnerId());
+
+ panel.addComponent(m_ImageOwnerIdInput);
+
+ m_ImageIdSelect = new Select("Image ID");
+ createImageItems();
+ panel.addComponent(m_ImageIdSelect);
+
+ m_ImageOwnerIdInput.addListener(new Property.ValueChangeListener() {
+ public void valueChange(Property.ValueChangeEvent
valueChangeEvent) {
+ config.setImageOwnerId((String)
valueChangeEvent.getProperty().getValue());
+ m_ImageIdSelect.removeAllItems();
+
+ createImageItems();
+ }
+ });
+
+
+ m_keyPairInput = new TextField("Keypair", config.getKeyPair());
+ panel.addComponent(m_keyPairInput);
+
+ m_tagPrefixInput = new TextField("Tag prefix", config.getTagPrefix());
+ panel.addComponent(m_tagPrefixInput);
+
+ String[] extraPorts = config.getExtraPorts();
+ StringBuilder extraPortsValue = new StringBuilder();
+ for (String extraPort : extraPorts) {
+ extraPortsValue.append(extraPort).append(",");
+ }
+ m_extraPortsInput = new TextField("Extra ports (comma separated",
extraPortsValue.toString());
+ panel.addComponent(m_extraPortsInput);
+
+ m_runAsRootCheckbox = new CheckBox("Run as root",
config.isRunAsRoot());
+ panel.addComponent(m_runAsRootCheckbox);
+
+ m_privateKeyFileInput = new TextField("Private key file",
config.getPrivateKeyFile());
+ panel.addComponent(m_privateKeyFileInput);
+
+ m_vmOptionsInput = new TextField("VM options", config.getVmOptions());
+ panel.addComponent(m_vmOptionsInput);
+
+ m_launcherArgumentsInput = new TextField("Launcher arguments",
config.getLauncherArguments());
+ panel.addComponent(m_launcherArgumentsInput);
+
+ m_nodeBootstrapInput = new TextField("Node bootstrap script",
config.getNodeBootstrap());
+ panel.addComponent(m_nodeBootstrapInput);
+
+ m_aceLauncherInput = new TextField("ACE launcher",
config.getAceLauncher());
+ panel.addComponent(m_aceLauncherInput);
+
+ m_additionalObrDownloadsInput = new TextField("Additional OBR
downloads (comma separated", config.getAdditionalObrDownloads());
+ panel.addComponent(m_additionalObrDownloadsInput);
+
+ m_externalDownloadsInput = new TextField("External download urls
(comman separated", config.getExternalDownloadUrls());
+ panel.addComponent(m_externalDownloadsInput);
+
+ m_sshUserInput = new TextField("SSH username", "ec2-user");
+ panel.addComponent(m_sshUserInput);
+
panel.addComponent(propertiesTable);
m_factory.submit(m_statusGetter);
}
+ private void createHardwareItems(Set<? extends Hardware> hardwares) {
+ for (Hardware hardware : hardwares) {
+ m_hardwareIdSelect.addItem(hardware.getId());
+ m_hardwareIdSelect.setItemCaption(hardware.getId(),
hardware.getName());
+ if(hardware.getId().equals(config.getHardwareId())) {
+ m_hardwareIdSelect.select(hardware.getId());
+ }
+ }
+ }
+
+ private void createImageItems() {
+ Set<? extends Image> images = config.listImages();
+ for (Image image : images) {
+ m_ImageIdSelect.addItem(image.getId());
+ m_ImageIdSelect.setItemCaption(image.getId(), image.getName());
+ if(image.getId().endsWith(config.getImageId())) {
+ m_ImageIdSelect.select(image.getId());
+ }
+ }
+ }
+
@SuppressWarnings("serial")
private class ActionButton extends Button implements
NodeStatusHandler.NodeStatusListener, ClickListener {
private final Action m_action;
@@ -158,8 +271,49 @@ public class NodePanel extends Panel {
protected void doRun() {
try {
m_handler.setStatus(NodeStatus.STARTING);
- m_factory.getCloudService().start(m_targetId);
+
+ String sshUser = (String) m_sshUserInput.getValue();
+ String location = (String) m_locationInput.getValue();
+ String hardwareId = (String) m_hardwareIdSelect.getValue();
+ String imageOwnerId = (String) m_ImageOwnerIdInput.getValue();
+ String imageId = (String) m_ImageIdSelect.getValue();
+ String keyPair = (String) m_keyPairInput.getValue();
+ String tagPrefix = (String) m_tagPrefixInput.getValue();
+ String[] extraPorts =
((String)m_extraPortsInput.getValue()).split(",");
+ boolean runAsRoot = m_runAsRootCheckbox.booleanValue();
+ String privateKeyFile =
(String)m_privateKeyFileInput.getValue();
+ String vmOptions = (String)m_vmOptionsInput.getValue();
+ String laucherArgs =
(String)m_launcherArgumentsInput.getValue();
+ String nodeBootStrap = (String)m_nodeBootstrapInput.getValue();
+ String aceLauncher = (String)m_aceLauncherInput.getValue();
+ String additionalObrDownloads =
(String)m_additionalObrDownloadsInput.getValue();
+ String externalDownloads =
(String)m_externalDownloadsInput.getValue();
+
+ config.setSshUser(sshUser);
+ config.setLocation(location);
+ config.setHardwareId(hardwareId);
+
+ if(imageOwnerId.length() > 0) {
+ config.setImageOwnerId(imageOwnerId);
+ }
+
+ config.setImageId(imageId);
+ config.setKeyPair(keyPair);
+ config.setTagPrefix(tagPrefix);
+ config.setExtraPorts(extraPorts);
+ config.setRunAsRoot(runAsRoot);
+ config.setPrivateKeyFile(privateKeyFile);
+ config.setVmOptions(vmOptions);
+ config.setLauncherArguments(laucherArgs);
+ config.setNodeBootstrap(nodeBootStrap);
+ config.setAceLauncher(aceLauncher);
+ config.setAdditionalObrDownloads(additionalObrDownloads);
+ config.setExternalDownloadUrls(externalDownloads);
+
+ m_factory.getCloudService().start(m_targetId, config);
m_handler.setStatus(NodeStatus.INITIALIZING);
+ disableInputFields();
+
}
catch (Exception e) {
m_handler.setStatus(NodeStatus.ERROR);
@@ -168,7 +322,25 @@ public class NodePanel extends Panel {
m_factory.submit(m_statusGetter);
}
}
-
+
+ private void disableInputFields() {
+ m_locationInput.setEnabled(false);
+ m_hardwareIdSelect.setEnabled(false);
+ m_ImageOwnerIdInput.setEnabled(false);
+ m_ImageIdSelect.setEnabled(false);
+ m_keyPairInput.setEnabled(false);
+ m_tagPrefixInput.setEnabled(false);
+ m_extraPortsInput.setEnabled(false);
+ m_runAsRootCheckbox.setEnabled(false);
+ m_privateKeyFileInput.setEnabled(false);
+ m_vmOptionsInput.setEnabled(false);
+ m_launcherArgumentsInput.setEnabled(false);
+ m_nodeBootstrapInput.setEnabled(false);
+ m_aceLauncherInput.setEnabled(false);
+ m_additionalObrDownloadsInput.setEnabled(false);
+ m_externalDownloadsInput.setEnabled(false);
+ }
+
private class StopRunner extends LockedRunner {
@Override
protected void doRun() {