You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by wo...@apache.org on 2010/09/03 17:43:13 UTC
svn commit: r992334 - in /incubator/libcloud/sandbox/java/trunk: ./ lib/
src/base/ src/base/beans/ src/base/interfaces/ src/drivers/
src/drivers/amazon/ src/drivers/ibm/
Author: woodser
Date: Fri Sep 3 15:43:12 2010
New Revision: 992334
URL: http://svn.apache.org/viewvc?rev=992334&view=rev
Log:
MAJOR REVISION
- Addition of Amazon EC2 drivers (US East, US West, EU West, and AP Southeast)
- Use of Map<String, Object> for generic extra parameters
- Utility class of useful functions
- Parameter priority bug fix in ConnectionKey.java
- Many foundation improvements
Added:
incubator/libcloud/sandbox/java/trunk/lib/commons-codec-1.4.jar (with props)
incubator/libcloud/sandbox/java/trunk/src/base/ResponseHandler.java
- copied, changed from r979864, incubator/libcloud/sandbox/java/trunk/src/base/DefaultHandler.java
incubator/libcloud/sandbox/java/trunk/src/base/Utils.java
incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/
incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2APSEDriver.java
incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Connection.java
incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Driver.java
incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2EUWestDriver.java
incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Handler.java
incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2USEastDriver.java
incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2USWestDriver.java
Removed:
incubator/libcloud/sandbox/java/trunk/lib/commons-codec-1.3.jar
incubator/libcloud/sandbox/java/trunk/src/base/DefaultHandler.java
incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponseHandler.java
Modified:
incubator/libcloud/sandbox/java/trunk/.classpath
incubator/libcloud/sandbox/java/trunk/src/base/ConnectionKey.java
incubator/libcloud/sandbox/java/trunk/src/base/ConnectionUserAndKey.java
incubator/libcloud/sandbox/java/trunk/src/base/LoggingConnectionUserAndKey.java
incubator/libcloud/sandbox/java/trunk/src/base/Node.java
incubator/libcloud/sandbox/java/trunk/src/base/Providers.java
incubator/libcloud/sandbox/java/trunk/src/base/beans/NodeImage.java
incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java
incubator/libcloud/sandbox/java/trunk/src/base/interfaces/INode.java
incubator/libcloud/sandbox/java/trunk/src/base/interfaces/INodeDriver.java
incubator/libcloud/sandbox/java/trunk/src/drivers/Example.java
incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMConnection.java
incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMDriver.java
incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMHandler.java
Modified: incubator/libcloud/sandbox/java/trunk/.classpath
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/.classpath?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/.classpath (original)
+++ incubator/libcloud/sandbox/java/trunk/.classpath Fri Sep 3 15:43:12 2010
@@ -1,17 +1,17 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
- <classpathentry kind="lib" path="lib/apache-mime4j-0.6.jar"/>
- <classpathentry kind="lib" path="lib/commons-codec-1.3.jar"/>
- <classpathentry kind="lib" path="lib/commons-logging-1.1.1.jar"/>
- <classpathentry kind="lib" path="lib/httpclient-4.0.1.jar"/>
- <classpathentry kind="lib" path="lib/httpcore-4.0.1.jar"/>
- <classpathentry kind="lib" path="lib/httpmime-4.0.1.jar"/>
- <classpathentry kind="lib" path="lib/resolver.jar"/>
- <classpathentry kind="lib" path="lib/serializer.jar"/>
- <classpathentry kind="lib" path="lib/xercesImpl.jar"/>
- <classpathentry kind="lib" path="lib/xercesSamples.jar"/>
- <classpathentry kind="lib" path="lib/xml-apis.jar"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="lib" path="lib/apache-mime4j-0.6.jar"/>
+ <classpathentry kind="lib" path="lib/commons-logging-1.1.1.jar"/>
+ <classpathentry kind="lib" path="lib/httpclient-4.0.1.jar"/>
+ <classpathentry kind="lib" path="lib/httpcore-4.0.1.jar"/>
+ <classpathentry kind="lib" path="lib/httpmime-4.0.1.jar"/>
+ <classpathentry kind="lib" path="lib/resolver.jar"/>
+ <classpathentry kind="lib" path="lib/serializer.jar"/>
+ <classpathentry kind="lib" path="lib/xercesImpl.jar"/>
+ <classpathentry kind="lib" path="lib/xercesSamples.jar"/>
+ <classpathentry kind="lib" path="lib/xml-apis.jar"/>
+ <classpathentry kind="lib" path="lib/commons-codec-1.4.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
Added: incubator/libcloud/sandbox/java/trunk/lib/commons-codec-1.4.jar
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/lib/commons-codec-1.4.jar?rev=992334&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/libcloud/sandbox/java/trunk/lib/commons-codec-1.4.jar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: incubator/libcloud/sandbox/java/trunk/src/base/ConnectionKey.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/ConnectionKey.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/ConnectionKey.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/base/ConnectionKey.java Fri Sep 3 15:43:12 2010
@@ -4,14 +4,11 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
-import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
@@ -21,51 +18,56 @@ import org.apache.http.client.methods.Ht
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIUtils;
-import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.message.BasicNameValuePair;
import base.interfaces.IConnection;
import base.interfaces.INodeDriver;
+/*
+ * Manages a connection with a secret access key.
+ */
public class ConnectionKey implements IConnection {
protected String host;
protected int port;
- protected String userId;
+ protected String accessId;
- protected String key;
+ protected String accessKey;
protected boolean secure;
protected INodeDriver driver;
+
+ protected String action;
protected DefaultHttpClient httpClient;
protected HttpHost httpHost;
- public ConnectionKey(String key, boolean secure, String host, INodeDriver driver) {
- this.key = key;
+ public ConnectionKey(String accessKey, boolean secure, String host, INodeDriver driver) {
+ this.accessKey = accessKey;
this.secure = secure;
this.host = host;
this.driver = driver;
- this.userId = null; // subclass my initialize
- this.port = -1; // default port used by HTTPComponents
+ this.accessId = null; // subclass may initialize
+ this.port = -1; // default port used by HTTPComponents
+ this.action = null;
}
- public ConnectionKey(String key, boolean secure, String host, int port,
+ public ConnectionKey(String accessKey, boolean secure, String host, int port,
INodeDriver driver) {
- this.key = key;
+ this.accessKey = accessKey;
this.secure = secure;
this.host = host;
this.port = port;
this.driver = driver;
this.httpClient = null;
this.httpHost = null;
- this.userId = null; // subclass my initialize
+ this.accessId = null; // subclass may initialize
+ this.action = null;
}
public void connect() {
@@ -77,15 +79,17 @@ public class ConnectionKey implements IC
this.port = port;
httpClient = new DefaultHttpClient();
- if (userId != null) {
+ if (accessId != null) {
httpClient.getCredentialsProvider().setCredentials(
new AuthScope(host, port),
- new UsernamePasswordCredentials(userId, key));
+ new UsernamePasswordCredentials(accessId, accessKey));
}
}
public Response request(String method, String action,
Map<String, String> headers, Map<String, String> params, String data) {
+ this.action = action;
+
// Connect if not already connected
if (httpClient == null) {
connect();
@@ -93,37 +97,27 @@ public class ConnectionKey implements IC
// Compose request headers with priority
Map<String, String> reqHeaders = new HashMap<String, String>();
- reqHeaders.put("User-Agent", getUserAgent()); // 3: libcloud headers
+ reqHeaders.put("User-Agent", getUserAgent()); // 3: libcloud headers
reqHeaders.put("Host", host);
- reqHeaders = addDefaultHeaders(reqHeaders); // 2: provider headers
- if (headers != null) {
- reqHeaders.putAll(headers); // 1: argument headers
- }
-
+ if (headers != null) reqHeaders.putAll(headers); // 2: argument headers
+ reqHeaders = addDefaultHeaders(reqHeaders); // 1: provider headers
+
// Compose request parameters with priority
- Map<String, String> reqParams = new HashMap<String, String>();
- reqParams = addDefaultParams(reqParams); // 2: provider parameters
- if (params != null) {
- reqParams.putAll(params); // 1: argument parameters
- }
-
- // Convert parameters to list for URLEncodedUtils
- List<NameValuePair> paramsNVP = new ArrayList<NameValuePair>();
- for (String name : reqParams.keySet()) {
- paramsNVP.add(new BasicNameValuePair(name, reqParams.get(name)));
- }
+ Map<String, String> reqParams = (params != null ? params // 2: argument parameters
+ : new HashMap<String, String>());
+ reqParams = addDefaultParams(reqParams); // 1: provider parameters
// Create URI endpoint
URI uri = null;
try {
String protocol = secure ? "https" : "http";
uri = URIUtils.createURI(protocol, host, port, action,
- URLEncodedUtils.format(paramsNVP, "UTF-8"), null);
+ Utils.urlEncodeMap(reqParams), null);
} catch (URISyntaxException e) {
e.printStackTrace();
return null;
}
-
+
// Create request to send
HttpUriRequest request = null;
if (method.equalsIgnoreCase("GET")) {
@@ -177,25 +171,6 @@ public class ConnectionKey implements IC
public String encodeData(String data) {
return data;
}
-
- /*
- * Utility that performs UTF-8 encoding of a map of Strings. Returns a
- * String that is suitable for use as an application/x-www-form-urlencoded
- * list of parameters in an HTTP PUT or HTTP POST.
- *
- * @param dataMap is the map of String values to format as a UTF-8 String
- *
- * @return String is the UTF-8 encoding of the map of String values
- */
- public String encodeDataMap(Map<String, String> dataMap) {
- // Convert map to List<NameValuePair> for URLEncodedUtils
- List<BasicNameValuePair> nvp = new ArrayList<BasicNameValuePair>();
- for (String key : dataMap.keySet()) {
- nvp.add(new BasicNameValuePair(key, dataMap.get(key)));
- }
-
- return URLEncodedUtils.format(nvp, "UTF-8");
- }
/*
* Defines the user agent used when making requests.
Modified: incubator/libcloud/sandbox/java/trunk/src/base/ConnectionUserAndKey.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/ConnectionUserAndKey.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/ConnectionUserAndKey.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/base/ConnectionUserAndKey.java Fri Sep 3 15:43:12 2010
@@ -4,15 +4,15 @@ import base.interfaces.INodeDriver;
public class ConnectionUserAndKey extends ConnectionKey {
- public ConnectionUserAndKey(String userId, String key, boolean secure,
+ public ConnectionUserAndKey(String accessId, String accessKey, boolean secure,
String host, int port, INodeDriver driver) {
- super(key, secure, host, port, driver);
- this.userId = userId;
+ super(accessKey, secure, host, port, driver);
+ this.accessId = accessId;
}
- public ConnectionUserAndKey(String userId, String key, boolean secure,
+ public ConnectionUserAndKey(String accessId, String accessKey, boolean secure,
String host, INodeDriver driver) {
- super(key, secure, host, driver);
- this.userId = userId;
+ super(accessKey, secure, host, driver);
+ this.accessId = accessId;
}
}
Modified: incubator/libcloud/sandbox/java/trunk/src/base/LoggingConnectionUserAndKey.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/LoggingConnectionUserAndKey.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/LoggingConnectionUserAndKey.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/base/LoggingConnectionUserAndKey.java Fri Sep 3 15:43:12 2010
@@ -4,10 +4,9 @@ import base.interfaces.INodeDriver;
public class LoggingConnectionUserAndKey extends LoggingConnection {
- public LoggingConnectionUserAndKey(String userId, String key, boolean secure,
+ public LoggingConnectionUserAndKey(String accessId, String accessKey, boolean secure,
String host, int port, INodeDriver driver) {
- super(key, secure, host, port, driver);
- this.userId = userId;
+ super(accessKey, secure, host, port, driver);
+ this.accessId = accessId;
}
-
}
Modified: incubator/libcloud/sandbox/java/trunk/src/base/Node.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/Node.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/Node.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/base/Node.java Fri Sep 3 15:43:12 2010
@@ -18,11 +18,11 @@ public class Node implements INode {
private String privateIp;
- private Map<String, String> extra;
+ private Map<String, Object> extra;
private INodeDriver driver;
- public Node(String id, String name, NodeState state, String publicIp, String privateIp, Map<String, String> extra, INodeDriver driver) {
+ public Node(String id, String name, NodeState state, String publicIp, String privateIp, Map<String, Object> extra, INodeDriver driver) {
this.id = id;
this.name = name;
this.state = state;
@@ -44,7 +44,7 @@ public class Node implements INode {
return driver;
}
- public Map<String, String> getExtra() {
+ public Map<String, Object> getExtra() {
return extra;
}
Modified: incubator/libcloud/sandbox/java/trunk/src/base/Providers.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/Providers.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/Providers.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/base/Providers.java Fri Sep 3 15:43:12 2010
@@ -18,8 +18,9 @@ public class Providers {
public static enum Provider {
DUMMY,
EC2_US_EAST,
- EC2_EU_WEST,
EC2_US_WEST,
+ EC2_EU_WEST,
+ EC2_AP_SOUTHEAST,
ECP,
GOGRID,
RACKSPACE,
@@ -49,9 +50,10 @@ public class Providers {
providerMap.put(Provider.IBM, "drivers.ibm.IBMDriver");
providerMap.put(Provider.RACKSPACE, "drivers.rackspace.XXX");
providerMap.put(Provider.SLICEHOST, "drivers.slicehost.XXX");
- providerMap.put(Provider.EC2_US_EAST, "");
- providerMap.put(Provider.EC2_EU_WEST, "");
- providerMap.put(Provider.EC2_US_WEST, "");
+ providerMap.put(Provider.EC2_US_EAST, "drivers.amazon.EC2USEastDriver");
+ providerMap.put(Provider.EC2_EU_WEST, "drivers.amazon.EC2EUWestDriver");
+ providerMap.put(Provider.EC2_US_WEST, "drivers.amazon.EC2USWestDriver");
+ providerMap.put(Provider.EC2_AP_SOUTHEAST, "drivers.amazon.EC2APSoutheastDriver");
providerMap.put(Provider.ECP, "");
providerMap.put(Provider.GOGRID, "");
providerMap.put(Provider.VPSNET, "");
Copied: incubator/libcloud/sandbox/java/trunk/src/base/ResponseHandler.java (from r979864, incubator/libcloud/sandbox/java/trunk/src/base/DefaultHandler.java)
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/ResponseHandler.java?p2=incubator/libcloud/sandbox/java/trunk/src/base/ResponseHandler.java&p1=incubator/libcloud/sandbox/java/trunk/src/base/DefaultHandler.java&r1=979864&r2=992334&rev=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/DefaultHandler.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/base/ResponseHandler.java Fri Sep 3 15:43:12 2010
@@ -1,15 +1,23 @@
package base;
import base.interfaces.IResponse;
-import base.interfaces.IResponseHandler;
-public class DefaultHandler implements IResponseHandler {
+/*
+ * Default handler for request responses. Subclasses should extend for custom
+ * processing.
+ */
+public class ResponseHandler {
protected IResponse response;
protected Object object;
- public DefaultHandler(IResponse response) {
+ /*
+ * Constructs the handler with the given response.
+ *
+ * @param response is the request's response
+ */
+ public ResponseHandler(IResponse response) {
this.response = response;
if (success()) {
@@ -19,23 +27,49 @@ public class DefaultHandler implements I
}
}
+ /*
+ * Returns the response's processed representation.
+ *
+ * @return Object is the response's parsed object for additional processing
+ */
public Object getParsedObject() {
return object;
}
+ /*
+ * Returns the original response.
+ *
+ * @return IResponse is the request's original response
+ */
public IResponse getResponse() {
return response;
}
- protected boolean success() {
- return response.getStatus() == 200;
- }
-
+ /*
+ * Parses the response's body. The parsed response is stored in 'object'.
+ * Subclasses should override for custom processing.
+ */
protected void parseBody() {
object = response.getBody();
}
+ /*
+ * Returns a String expressing the error that occurred. Subclasses should
+ * override for custom processing.
+ *
+ * @return String represents the error that occurred if !success()
+ */
protected String parseError() {
return response.getStatus() + " " + response.getPhrase();
}
+
+ /*
+ * Indicates if the request was successful or not. Subclasses should
+ * override for custom processing.
+ *
+ * @return true if the request was successful, false otherwise
+ */
+ protected boolean success() {
+ return response.getStatus() == 200;
+ }
}
Added: incubator/libcloud/sandbox/java/trunk/src/base/Utils.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/Utils.java?rev=992334&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/Utils.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/base/Utils.java Fri Sep 3 15:43:12 2010
@@ -0,0 +1,81 @@
+package base;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.message.BasicNameValuePair;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/*
+ * Useful utility functions for Apache libcloud.
+ */
+public class Utils {
+
+ /*
+ * Utility function to extract the text value of the given element.
+ *
+ * @param elem is the element to find the tag in
+ * @param tagName is the name of the tag to find the value for
+ *
+ * @return String is the text value of the given tag
+ */
+ public static String getTextValue(Element elem, String tagName) {
+ NodeList nl = elem.getElementsByTagName(tagName);
+ if (nl.getLength() > 0) {
+ if (nl.item(0).getFirstChild() == null) {
+ return "";
+ } else {
+ return nl.item(0).getFirstChild().getNodeValue();
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /*
+ * Utility function that returns a list of immediate children to the given
+ * Element and that matches the given tagName.
+ *
+ * TODO: Use XPath instead (see Amazon EC2 driver)
+ *
+ * @param elem is the parent of the elements to search
+ * @param tagName identifies the elements to find
+ *
+ * @return List<Element> is a list of immediate children matching tagName
+ */
+ public static List<Element> getFirstElementsByTagName(Element elem, String tagName) {
+ List<Element> elements = new ArrayList<Element>();
+ NodeList children = elem.getChildNodes();
+ for (int i = 0; i < children.getLength(); i++) {
+ Element child = (Element) children.item(i);
+ if (child.getTagName().equals(tagName)) {
+ elements.add(child);
+ }
+ }
+ return elements;
+ }
+
+ /*
+ * Utility that performs UTF-8 encoding of a map of Strings. Returns a
+ * String that is suitable for use as an application/x-www-form-urlencoded
+ * list of parameters in an HTTP PUT or HTTP POST.
+ *
+ * TODO: Use XPath instead (see Amazon EC2 driver)
+ *
+ * @param map is the map of String values to format as a UTF-8 String
+ *
+ * @return String is the UTF-8 encoding of the map of String values
+ */
+ public static String urlEncodeMap(Map<String, String> map) {
+ // Convert map to List<NameValuePair> for URLEncodedUtils
+ List<BasicNameValuePair> nvp = new ArrayList<BasicNameValuePair>();
+ for (String key : new TreeSet<String>(map.keySet())) { // preserve order
+ nvp.add(new BasicNameValuePair(key, map.get(key)));
+ }
+ return URLEncodedUtils.format(nvp, "UTF-8");
+ }
+}
Modified: incubator/libcloud/sandbox/java/trunk/src/base/beans/NodeImage.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/beans/NodeImage.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/beans/NodeImage.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/base/beans/NodeImage.java Fri Sep 3 15:43:12 2010
@@ -10,11 +10,11 @@ public class NodeImage {
public String name;
- public Map<String, String> extra;
+ public Map<String, Object> extra;
public INodeDriver driver;
- public NodeImage(String id, String name, Map<String, String> extra, INodeDriver driver) {
+ public NodeImage(String id, String name, Map<String, Object> extra, INodeDriver driver) {
this.id = id;
this.name = name;
this.extra = extra;
Modified: incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java Fri Sep 3 15:43:12 2010
@@ -18,7 +18,4 @@ public interface IConnection {
public Map<String, String> addDefaultParams(Map<String, String> params);
public String encodeData(String data);
-
- // TODO: better way to handle URL encoding maps?
- public String encodeDataMap(Map<String, String> dataMap);
}
Modified: incubator/libcloud/sandbox/java/trunk/src/base/interfaces/INode.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/interfaces/INode.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/interfaces/INode.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/base/interfaces/INode.java Fri Sep 3 15:43:12 2010
@@ -24,5 +24,5 @@ public interface INode {
public INodeDriver getDriver();
- public Map<String, String> getExtra();
+ public Map<String, Object> getExtra();
}
Modified: incubator/libcloud/sandbox/java/trunk/src/base/interfaces/INodeDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/interfaces/INodeDriver.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/base/interfaces/INodeDriver.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/base/interfaces/INodeDriver.java Fri Sep 3 15:43:12 2010
@@ -12,7 +12,7 @@ public interface INodeDriver {
public INode createNode(String name, NodeSize size,
NodeImage image, NodeLocation location, NodeAuth auth,
- Map<String, String> extra);
+ Map<String, Object> extra);
public boolean destroyNode(INode node);
Modified: incubator/libcloud/sandbox/java/trunk/src/drivers/Example.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/Example.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/Example.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/Example.java Fri Sep 3 15:43:12 2010
@@ -6,6 +6,11 @@ import java.util.List;
import base.NodeDriver;
import base.Providers;
import base.Providers.Provider;
+import base.beans.NodeImage;
+import base.beans.NodeLocation;
+import base.beans.NodeSize;
+import base.interfaces.INode;
+import drivers.amazon.EC2USEastDriver;
import drivers.ibm.IBMDriver;
/*
@@ -19,19 +24,27 @@ public class Example {
public static void main(String[] args) {
// Fetch driver(s).
Class<NodeDriver> ibmClass = Providers.getDriver(Provider.IBM);
- IBMDriver ibmDriver = (IBMDriver)Providers.constructDriver(ibmClass, "your_username", "your_password");
+ IBMDriver ibmDriver = (IBMDriver)Providers.constructDriver(ibmClass, "username", "password");
+ Class<NodeDriver> ec2USEastClass = Providers.getDriver(Provider.EC2_US_EAST);
+ EC2USEastDriver ec2USEastDriver = (EC2USEastDriver)Providers.constructDriver(ec2USEastClass, "access key id", "access key");
// Insert driver(s) into array for generic processing.
List<NodeDriver> drivers = new ArrayList<NodeDriver>();
drivers.add(ibmDriver);
+ drivers.add(ec2USEastDriver);
// Process drivers.
for (NodeDriver driver : drivers) {
System.out.println(driver.getName() + ':');
- System.out.println("\tNodes: " + driver.listNodes());
- System.out.println("\tImages: " + driver.listImages());
- System.out.println("\tSizes: " + driver.listSizes());
- System.out.println("\tLocations: " + driver.listLocations());
+ List<INode> nodes = driver.listNodes();
+ List<NodeImage> images = driver.listImages();
+ List<NodeSize> sizes = driver.listSizes();
+ List<NodeLocation> locations = driver.listLocations();
+
+ System.out.println("\t" + nodes.size() + " Nodes: " + nodes);
+ System.out.println("\t" + images.size() + " Images: " + images);
+ System.out.println("\t" + sizes.size() + " Sizes: " + sizes);
+ System.out.println("\t" + locations.size() + " Locations: " + locations);
}
}
}
Added: incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2APSEDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2APSEDriver.java?rev=992334&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2APSEDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2APSEDriver.java Fri Sep 3 15:43:12 2010
@@ -0,0 +1,46 @@
+package drivers.amazon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import base.beans.NodeLocation;
+
+public class EC2APSEDriver extends EC2Driver {
+
+ private static final String EC2_AP_SE_HOST = "ec2.ap-southeast-1.amazonaws.com";
+
+ private static final Map<String, Float> EC2_AP_SE_PRICES = initNodePrices();
+
+ public EC2APSEDriver(String accessId, String accessKey) {
+ super(accessId, accessKey, EC2_AP_SE_HOST);
+ }
+
+ public List<NodeLocation> listLocations() {
+ List<NodeLocation> locations = new ArrayList<NodeLocation>();
+ locations.add(new NodeLocation("0", "Amazon Asia-Pacific Singapore", "SG", this));
+ return locations;
+ }
+
+ public String getName() {
+ return "Amazon EC2 (ap-southeast-1)";
+ }
+
+ protected float getPrice(String sizeId) {
+ return EC2_AP_SE_PRICES.get(sizeId);
+ }
+
+ private static Map<String, Float> initNodePrices() {
+ Map<String, Float> prices = new HashMap<String, Float>();
+ prices.put("m1.small", .095f);
+ prices.put("m1.large", .38f);
+ prices.put("m1.xlarge", .76f);
+ prices.put("c1.medium", .19f);
+ prices.put("c1.xlarge", .76f);
+ prices.put("m2.xlarge", .57f);
+ prices.put("m2.2xlarge", 1.14f);
+ prices.put("m2.4xlarge", 2.28f);
+ return prices;
+ }
+}
Added: incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Connection.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Connection.java?rev=992334&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Connection.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Connection.java Fri Sep 3 15:43:12 2010
@@ -0,0 +1,77 @@
+package drivers.amazon;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SimpleTimeZone;
+import java.util.TreeSet;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+
+import base.ConnectionUserAndKey;
+import base.Utils;
+import base.interfaces.INodeDriver;
+
+public class EC2Connection extends ConnectionUserAndKey {
+
+ private static final boolean DEFAULT_SECURE = true;
+
+ private static final String API_VERSION = "2010-06-15";
+
+ public EC2Connection(String accessId, String accessKey, String host,
+ INodeDriver driver) {
+ super(accessId, accessKey, DEFAULT_SECURE, host, driver);
+ }
+
+ public Map<String, String> addDefaultParams(Map<String, String> params) {
+ params.put("SignatureVersion", "2");
+ params.put("SignatureMethod", "HmacSHA256");
+ params.put("AWSAccessKeyId", accessId);
+ params.put("Version", API_VERSION);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+ sdf.setTimeZone(new SimpleTimeZone(0, "GMT"));
+ params.put("Timestamp", sdf.format(new Date()));
+ params.put("Signature", getAWSAuthParams(params, accessKey, action));
+ return params;
+ }
+
+ /*
+ * Generates the request signature as defined at:
+ * http://docs.amazonwebservices.com/AWSEC2/2010-06-15/DeveloperGuide/index.html?using-query-api.html
+ */
+ private String getAWSAuthParams(Map<String, String> params, String accessKey, String path) {
+ // Sort the parameters by key
+ TreeSet<String> sortedKeys = new TreeSet<String>(params.keySet());
+ Map<String, String> sortedParams = new HashMap<String, String>();
+ for (String key : sortedKeys){
+ sortedParams.put(key, params.get(key));
+ }
+
+ // Generate stringToSign
+ String qs = Utils.urlEncodeMap(sortedParams);
+ qs = qs.replace("+", "%20");
+ String stringToSign = "GET\n" + host + '\n' + path + '\n' + qs;
+
+ // Calculate HMAC of stringToSign
+ byte[] hmac = null;
+ try {
+ Mac mac = Mac.getInstance("HmacSHA256");
+ SecretKeySpec key = new SecretKeySpec(accessKey.getBytes(), "UTF-8");
+ mac.init(key);
+ hmac = mac.doFinal(stringToSign.getBytes());
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (InvalidKeyException e) {
+ e.printStackTrace();
+ }
+
+ // Base 64 encode HMAC
+ return new String(Base64.encodeBase64(hmac));
+ }
+}
Added: incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Driver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Driver.java?rev=992334&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Driver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Driver.java Fri Sep 3 15:43:12 2010
@@ -0,0 +1,403 @@
+package drivers.amazon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.codec.binary.Base64;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import base.Node;
+import base.NodeDriver;
+import base.NodeState;
+import base.beans.NodeAuth;
+import base.beans.NodeImage;
+import base.beans.NodeLocation;
+import base.beans.NodeSize;
+import base.interfaces.INode;
+import base.interfaces.IResponse;
+
+/*
+ * Base driver to interact with Amazon EC2.
+ *
+ * TODO: comment ec2 classes
+ * TODO: Formal tests of EC2 drivers
+ */
+public abstract class EC2Driver extends NodeDriver {
+
+ private XPath xpath;
+ protected static final String API_VERSION = "2010-06-15";
+ protected static final String NAMESPACE = "http://ec2.amazonaws.com/doc/" + API_VERSION + "/";
+ private static final Map<String, NodeSize> NODE_SIZES = initNodeSizes();
+ private static final Map<String, NodeState> NODE_STATE_MAP = new HashMap<String, NodeState>();
+
+ /*
+ * Constructs the base driver for location-specific drivers to subclass.
+ *
+ * @param accessId is the user's Amazon access key ID
+ * @param accessKey is the user's Amazon secret key
+ */
+ public EC2Driver(String accessId, String accessKey, String host) {
+ connection = new EC2Connection(accessId, accessKey, host, this);
+ xpath = XPathFactory.newInstance().newXPath();
+
+ // Map Amazon EC2 instance states to libcloud
+ NODE_STATE_MAP.put("pending", NodeState.PENDING);
+ NODE_STATE_MAP.put("running", NodeState.RUNNING);
+ NODE_STATE_MAP.put("shutting-down", NodeState.TERMINATED);
+ NODE_STATE_MAP.put("terminated", NodeState.TERMINATED);
+ NODE_STATE_MAP.put("stopping", NodeState.PENDING);
+ NODE_STATE_MAP.put("stopped", NodeState.TERMINATED);
+ }
+
+ /*
+ * Creates a node on Amazon EC2.
+ *
+ * See http://bit.ly/8ZyPSy [docs.amazonwebservices.com]
+ *
+ * Supported keyword arguments:
+ * ex_mincount: Minimum number of instances to launch
+ * ex_maxcount: Maximum number of instances to launch
+ * ex_securitygroup: Name of security group(s)
+ * ex_keyname: The name of the key pair
+ * ex_userdata: User data
+ */
+ @SuppressWarnings("unchecked")
+ public INode createNode(String name, NodeSize size, NodeImage image,
+ NodeLocation location, NodeAuth auth, Map<String, Object> extra) {
+ // Add base parameters
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("Action", "RunInstances");
+ params.put("ImageId", image.id);
+ params.put("InstanceType", size.id);
+ params.put("MinCount", "1");
+ params.put("MaxCount", "1");
+
+ // Process extra map
+ if (extra != null) {
+ // Minimum & Maximum nodes to create
+ if (extra.containsKey("ex_mincount")) {
+ params.put("MinCount", (String)extra.get("ex_mincount"));
+ }
+ if (extra.containsKey("ex_maxcount")) {
+ params.put("MaxCount", (String)extra.get("ex_maxcount"));
+ }
+
+ // SecurityGroups
+ if (extra.containsKey("ex_securitygroup")) {
+ Object securityGroup = extra.get("ex_securitygroup");
+ List<String> groups = null;
+ if (securityGroup instanceof List) {
+ groups = (List<String>)securityGroup;
+ } else {
+ groups = new ArrayList<String>();
+ groups.add((String)securityGroup);
+ }
+ for (int i = 0; i < groups.size(); i++) {
+ params.put("SecurityGroup." + (i + 1), groups.get(i));
+ }
+ }
+
+ // KeyName
+ if (extra.containsKey("ex_keyname")) {
+ params.put("KeyName", (String)extra.get("ex_keyname"));
+ }
+
+ // UserData
+ if (extra.containsKey("ex_userdata")) {
+ String userData = (String)extra.get("ex_userdata");
+ params.put("UserData", new String(Base64.encodeBase64(userData.getBytes())));
+ }
+ }
+
+ // Send & process request
+ IResponse response = connection.request("GET", "/", null, params, null);
+ EC2Handler handler = new EC2Handler(response);
+ return parseNodes(((Document)handler.getParsedObject()).getDocumentElement(), "instancesSet/item", null).get(0);
+ }
+
+ public boolean destroyNode(INode node) {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("Action", "TerminateInstances");
+ String[] values = {node.getId()};
+ params.putAll(pathList("InstanceId", values));
+ IResponse response = connection.request("GET", "/", null, params, null);
+ EC2Handler handler = new EC2Handler(response);
+ return parseTerminateBoolean((Document)handler.getParsedObject());
+ }
+
+ public boolean rebootNode(INode node) {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("Action", "RebootInstances");
+ String[] values = {node.getId()};
+ params.putAll(pathList("InstanceId", values));
+ IResponse response = connection.request("GET", "/", null, params, null);
+ EC2Handler handler = new EC2Handler(response);
+ return parseRebootBoolean(((Document)handler.getParsedObject()));
+ }
+
+ public List<INode> listNodes() {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("Action", "DescribeInstances");
+ IResponse response = connection.request("GET", "/", null, params, null);
+ EC2Handler handler = new EC2Handler(response);
+ return parseNodesByGroup(((Document)handler.getParsedObject()).getDocumentElement());
+ }
+
+ public List<NodeImage> listImages() {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("Action", "DescribeImages");
+ IResponse response = connection.request("GET", "/", null, params, null);
+ EC2Handler handler = new EC2Handler(response);
+ return parseImages((Document)handler.getParsedObject());
+ }
+
+ public List<NodeSize> listSizes() {
+ List<NodeSize> sizes = new ArrayList<NodeSize>();
+ for (NodeSize size : NODE_SIZES.values()) {
+ sizes.add(new NodeSize(size.id, size.name, size.ram, size.disk,
+ size.bandwidth, getPrice(size.id), this));
+ }
+ return sizes;
+ }
+
+ /*
+ * Creates a new Security Group.
+ *
+ * Note: This is a non-standard extension API and only works with EC2.
+ *
+ * TODO: Test this method.
+ *
+ * @param name is the nam eof the security group to create
+ * @param description is a human-readable description of the group
+ *
+ * @return Object is the parsed object as defined and handled by EC2Handler
+ */
+ public Object exCreateSecurityGroup(String name, String description) {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("Action", "CreateSecurityGroup");
+ params.put("GroupName", name);
+ params.put("GroupDescription", description);
+ IResponse response = connection.request("GET", "/", null, params, null);
+ EC2Handler handler = new EC2Handler(response);
+ return handler.getParsedObject();
+ }
+
+ /*
+ * Edit a Security Group to allow all traffic.
+ *
+ * Note: This is a non-standard extension API and only works with EC2.
+ *
+ * TODO: Test this method.
+ *
+ * @param name is the name of the security group to edit
+ *
+ * @return List<Object> is a list of parsed objects as defined & handled by EC2Handler
+ */
+ public List<Object> exAuthorizeSecurityGroupPermissive(String name) {
+ List<Object> results = new ArrayList<Object>();
+
+ // Request 1
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("Action", "AuthorizeSecurityGroupIngress");
+ params.put("GroupName", name);
+ params.put("IpProtocol", "tcp");
+ params.put("FromPort", "0");
+ params.put("ToPort", "65535");
+ params.put("CidrIp", "0.0.0.0/0");
+ try {
+ IResponse response = connection.request("GET", "/", null, params, null);
+ EC2Handler handler = new EC2Handler(response);
+ results.add(handler.getParsedObject());
+ } catch(Exception e) {
+ if (!e.getMessage().contains("InvalidPermission.Duplicate")) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // Request 2
+ params.put("IpProtocol", "udo");
+ try {
+ IResponse response = connection.request("GET", "/", null, params, null);
+ EC2Handler handler = new EC2Handler(response);
+ results.add(handler.getParsedObject());
+ } catch(Exception e) {
+ if (!e.getMessage().contains("InvalidPermission.Duplicate")) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // Request 3
+ params.put("IpProtocol", "icmp");
+ params.put("FromPort", "-1");
+ params.put("ToPort", "-1");
+ try {
+ IResponse response = connection.request("GET", "/", null, params, null);
+ EC2Handler handler = new EC2Handler(response);
+ results.add(handler.getParsedObject());
+ } catch(Exception e) {
+ if (!e.getMessage().contains("InvalidPermission.Duplicate")) {
+ throw new RuntimeException(e);
+ }
+ }
+ return results;
+ }
+
+ // ----------------------------- HIDDEN HELPERS ---------------------------
+ private List<INode> parseNodesByGroup(Element elem) {
+ try {
+ List<INode> nodes = new ArrayList<INode>();
+ NodeList reservationList = (NodeList)xpath.evaluate("reservationSet/item", elem, XPathConstants.NODESET);
+ for (int rIdx = 0; rIdx < reservationList.getLength(); rIdx++) {
+ Element rs = (Element)reservationList.item(rIdx);
+ List<String> groups = new ArrayList<String>();
+ NodeList groupList = (NodeList)xpath.evaluate("groupSet/item", rs, XPathConstants.NODESET);
+ for (int gsIdx = 0; gsIdx < groupList.getLength(); gsIdx++) {
+ groups.add(xpath.evaluate("groupId", groupList.item(gsIdx)));
+ }
+ nodes.addAll(parseNodes(rs, "instancesSet/item", groups));
+ }
+ return nodes;
+ } catch (XPathExpressionException e) {
+ e.printStackTrace();
+ }
+ return null; // Error
+ }
+
+ private List<INode> parseNodes(Element elem, String path, List<String> groups) {
+ try {
+ List<INode> nodes = new ArrayList<INode>();
+ NodeList instanceSet = (NodeList)xpath.evaluate(path, elem, XPathConstants.NODESET);
+ for (int i = 0; i < instanceSet.getLength(); i++) {
+ nodes.add(parseNode((Element)instanceSet.item(i), groups));
+ }
+ return nodes;
+ } catch (XPathExpressionException e) {
+ e.printStackTrace();
+ }
+ return null; // Error
+ }
+
+ private INode parseNode(Element elem, List<String> groups) throws XPathExpressionException {
+ // Node parameters
+ String id = xpath.evaluate("instanceId", elem);
+ String name = xpath.evaluate("instanceId", elem);
+ NodeState state = NODE_STATE_MAP.get(xpath.evaluate("instanceState/name", elem));
+ String publicIp = xpath.evaluate("dnsName", elem);
+ String privateIp = xpath.evaluate("privateDnsName", elem);
+
+ // Extra parameter
+ Map<String, Object> extra = new HashMap<String, Object>();
+ extra.put("dnsName", xpath.evaluate("dnsName", elem));
+ extra.put("instanceId", xpath.evaluate("instanceId", elem));
+ extra.put("imageId", xpath.evaluate("imageId", elem));
+ extra.put("privateDns", xpath.evaluate("privateDns", elem));
+ extra.put("status", xpath.evaluate("instanceState/name", elem));
+ extra.put("keyName", xpath.evaluate("keyName", elem));
+ extra.put("launchIndex", xpath.evaluate("amiLaunchIndex", elem));
+ NodeList productSet = (NodeList)xpath.evaluate("productCodesSet/item", elem, XPathConstants.NODESET);
+ List<String> productCodes = new ArrayList<String>();
+ for (int i = 0; i < productSet.getLength(); i++) {
+ productCodes.add(xpath.evaluate("productCode", productSet.item(i)));
+ }
+ extra.put("productCode", productCodes);
+ extra.put("instanceType", xpath.evaluate("instanceType", elem));
+ extra.put("launchdatetime", xpath.evaluate("launchTime", elem));
+ extra.put("availability", xpath.evaluate("placement/availabilityZone", elem));
+ extra.put("kernelId", xpath.evaluate("kernelId", elem));
+ extra.put("ramdiskId", xpath.evaluate("ramdiskId", elem));
+ if (groups != null) extra.put("groups", groups);
+
+ // Construct final node and return!
+ return new Node(id, name, state, publicIp, privateIp, extra, this);
+ }
+
+ private List<NodeImage> parseImages(Document doc) {
+ List<NodeImage> images = new ArrayList<NodeImage>();
+ try {
+ NodeList imageSet = (NodeList)xpath.evaluate("imagesSet/item", doc.getDocumentElement(), XPathConstants.NODESET);
+ for (int i = 0; i < imageSet.getLength(); i++) {
+ images.add(parseImage((Element)imageSet.item(i)));
+ }
+ return images;
+ } catch (XPathExpressionException e) {
+ e.printStackTrace();
+ }
+ return null; // Error
+ }
+
+ private NodeImage parseImage(Element elem) throws XPathExpressionException {
+ return new NodeImage(xpath.evaluate("imageId", elem),
+ xpath.evaluate("imageLocation", elem),
+ null,
+ this);
+ }
+
+ /*
+ * Converts a key and array of values into a map for AWS query parameters.
+ *
+ * @param key is the key for the array of values
+ * @param values are the values to compose the query
+ *
+ * @return Map<String, String> are parameters for the AWS query
+ */
+ private Map<String, String> pathList(String key, String[] values) {
+ Map<String, String> params = new HashMap<String, String>();
+ for (int i = 0; i < values.length; i++) {
+ params.put(key + '.' + (i + 1), values[i]);
+ }
+ return params;
+ }
+
+ private boolean parseRebootBoolean(Document doc) {
+ try {
+ return ((String)xpath.evaluate("return", doc.getDocumentElement())).equals("true");
+ } catch (XPathExpressionException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ private boolean parseTerminateBoolean(Document doc) {
+ try {
+ String currentState = (String)xpath.evaluate("instancesSet/item/currentState/name", doc.getDocumentElement());
+ return currentState.equals("shutting-down") || currentState.equals("terminated");
+ } catch (XPathExpressionException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ /*
+ * Base Amazon EC2 instance types. Subclasses set the prices.
+ */
+ protected static Map<String, NodeSize> initNodeSizes() {
+ Map<String, NodeSize> sizes = new HashMap<String, NodeSize>();
+ sizes.put("m1.small", new NodeSize("m1.small", "Small Instance", 1740, 160, -1, -1f, null));
+ sizes.put("m1.large", new NodeSize("m1.large", "Large Instance", 7680, 850, -1, -1f, null));
+ sizes.put("m1.xlarge", new NodeSize("m1.xlarge", "Extra Large Instance", 15360, 1690, -1, -1f, null));
+ sizes.put("c1.medium", new NodeSize("c1.medium", "High-CPU Medium Instance", 1740, 350, -1, -1f, null));
+ sizes.put("c1.xlarge", new NodeSize("c1.xlarge", "High-CPU Extra Large Instance", 7680, 1960, -1, -1f, null));
+ sizes.put("m2.xlarge", new NodeSize("m2.xlarge", "High-Memory Extra Large Instance", 17510, 420, -1, -1f, null));
+ sizes.put("m2.2xlarge", new NodeSize("m2.2xlarge", "High-Memory Double Extra Large Instance", 35021, 850, -1, -1f, null));
+ sizes.put("m2.4xlarge", new NodeSize("m2.4xlarge", "High-Memory Quadruple Extra Large Instance", 70042, 1690, -1, -1f, null));
+ return sizes;
+ }
+
+ /*
+ * Retrieves the price for a NodeSize. Subclass implements its own prices.
+ *
+ * @param sizeId identifies the node configuration
+ *
+ * @return float is the price of the node configuration
+ */
+ protected abstract float getPrice(String sizeId);
+}
Added: incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2EUWestDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2EUWestDriver.java?rev=992334&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2EUWestDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2EUWestDriver.java Fri Sep 3 15:43:12 2010
@@ -0,0 +1,46 @@
+package drivers.amazon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import base.beans.NodeLocation;
+
+public class EC2EUWestDriver extends EC2Driver {
+
+ private static final String EC2_EU_WEST_HOST = "ec2.eu-west-1.amazonaws.com";
+
+ private static final Map<String, Float> EC2_EU_WEST_PRICES = initNodePrices();
+
+ public EC2EUWestDriver(String accessId, String accessKey) {
+ super(accessId, accessKey, EC2_EU_WEST_HOST);
+ }
+
+ public List<NodeLocation> listLocations() {
+ List<NodeLocation> locations = new ArrayList<NodeLocation>();
+ locations.add(new NodeLocation("0", "Amazon Europe Ireland", "IE", this));
+ return locations;
+ }
+
+ public String getName() {
+ return "Amazon EC2 (eu-west-1)";
+ }
+
+ protected float getPrice(String sizeId) {
+ return EC2_EU_WEST_PRICES.get(sizeId);
+ }
+
+ private static Map<String, Float> initNodePrices() {
+ Map<String, Float> prices = new HashMap<String, Float>();
+ prices.put("m1.small", .095f);
+ prices.put("m1.large", .38f);
+ prices.put("m1.xlarge", .76f);
+ prices.put("c1.medium", .19f);
+ prices.put("c1.xlarge", .76f);
+ prices.put("m2.xlarge", .57f);
+ prices.put("m2.2xlarge", 1.14f);
+ prices.put("m2.4xlarge", 2.28f);
+ return prices;
+ }
+}
Added: incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Handler.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Handler.java?rev=992334&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Handler.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2Handler.java Fri Sep 3 15:43:12 2010
@@ -0,0 +1,82 @@
+package drivers.amazon;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import base.ResponseHandler;
+import base.exceptions.InvalidCredsException;
+import base.interfaces.IResponse;
+
+public class EC2Handler extends ResponseHandler {
+
+ public EC2Handler(IResponse response) {
+ super(response);
+ }
+
+ protected void parseBody() {
+ object = null;
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ object = db.parse(new InputSource(new StringReader(response.getBody())));
+ } catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ } catch (SAXException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected String parseError() {
+ try {
+ // Parse errors
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.parse(new InputSource(new StringReader(response.getBody())));
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ NodeList errors = (NodeList)xpath.evaluate("Errors/Error", doc.getDocumentElement(), XPathConstants.NODESET);
+
+ // Process errors
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < errors.getLength(); i++) {
+ String error = (String)xpath.evaluate("Code", errors.item(i));
+ String message = (String)xpath.evaluate("Message", errors.item(i));
+ if (error.equals("InvalidClientTokenId")) {
+ throw new InvalidCredsException(response.getStatus() + " " + error + ": " + message);
+ } else if (error.equals("SignatureDoesNotMatch")) {
+ throw new InvalidCredsException(response.getStatus() + " " + error + ": " + message);
+ } else if (error.equals("AuthFailure")) {
+ throw new InvalidCredsException(response.getStatus() + " " + error + ": " + message);
+ } else if (error.equals("OptInRequired")) {
+ throw new InvalidCredsException(response.getStatus() + " " + error + ": " + message);
+ } else {
+ sb.append(response.getStatus() + " " + error + ": " + message + '\n');
+ }
+ }
+ return sb.toString().trim();
+ } catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ } catch (SAXException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (XPathExpressionException e) {
+ e.printStackTrace();
+ }
+ return super.parseError();
+ }
+}
Added: incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2USEastDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2USEastDriver.java?rev=992334&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2USEastDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2USEastDriver.java Fri Sep 3 15:43:12 2010
@@ -0,0 +1,46 @@
+package drivers.amazon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import base.beans.NodeLocation;
+
+public class EC2USEastDriver extends EC2Driver {
+
+ private static final String EC2_US_EAST_HOST = "ec2.us-east-1.amazonaws.com";
+
+ private static final Map<String, Float> EC2_US_EAST_PRICES = initNodePrices();
+
+ public EC2USEastDriver(String accessId, String accessKey) {
+ super(accessId, accessKey, EC2_US_EAST_HOST);
+ }
+
+ public List<NodeLocation> listLocations() {
+ List<NodeLocation> locations = new ArrayList<NodeLocation>();
+ locations.add(new NodeLocation("0", "Amazon US N. Virginia", "US", this));
+ return locations;
+ }
+
+ public String getName() {
+ return "Amazon EC2 (us-east-1)";
+ }
+
+ protected float getPrice(String sizeId) {
+ return EC2_US_EAST_PRICES.get(sizeId);
+ }
+
+ private static Map<String, Float> initNodePrices() {
+ Map<String, Float> prices = new HashMap<String, Float>();
+ prices.put("m1.small", .085f);
+ prices.put("m1.large", .34f);
+ prices.put("m1.xlarge", .68f);
+ prices.put("c1.medium", .17f);
+ prices.put("c1.xlarge", .68f);
+ prices.put("m2.xlarge", .50f);
+ prices.put("m2.2xlarge", 1.00f);
+ prices.put("m2.4xlarge", 2.00f);
+ return prices;
+ }
+}
Added: incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2USWestDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2USWestDriver.java?rev=992334&view=auto
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2USWestDriver.java (added)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/amazon/EC2USWestDriver.java Fri Sep 3 15:43:12 2010
@@ -0,0 +1,46 @@
+package drivers.amazon;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import base.beans.NodeLocation;
+
+public class EC2USWestDriver extends EC2Driver {
+
+ private static final String EC2_US_WEST_HOST = "ec2.us-west-1.amazonaws.com";
+
+ private static final Map<String, Float> EC2_US_WEST_PRICES = initNodePrices();
+
+ public EC2USWestDriver(String accessId, String accessKey) {
+ super(accessId, accessKey, EC2_US_WEST_HOST);
+ }
+
+ public List<NodeLocation> listLocations() {
+ List<NodeLocation> locations = new ArrayList<NodeLocation>();
+ locations.add(new NodeLocation("0", "Amazon US N. California", "US", this));
+ return locations;
+ }
+
+ public String getName() {
+ return "Amazon EC2 (us-west-1)";
+ }
+
+ protected float getPrice(String sizeId) {
+ return EC2_US_WEST_PRICES.get(sizeId);
+ }
+
+ private static Map<String, Float> initNodePrices() {
+ Map<String, Float> prices = new HashMap<String, Float>();
+ prices.put("m1.small", .095f);
+ prices.put("m1.large", .38f);
+ prices.put("m1.xlarge", .76f);
+ prices.put("c1.medium", .19f);
+ prices.put("c1.xlarge", .76f);
+ prices.put("m2.xlarge", .57f);
+ prices.put("m2.2xlarge", 1.14f);
+ prices.put("m2.4xlarge", 2.28f);
+ return prices;
+ }
+}
Modified: incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMConnection.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMConnection.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMConnection.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMConnection.java Fri Sep 3 15:43:12 2010
@@ -16,14 +16,14 @@ public class IBMConnection extends Conne
super(userId, key, DEFAULT_SECURE, DEFAULT_HOST, driver);
}
- public IBMConnection(String userId, String key, boolean secure,
+ public IBMConnection(String userId, String password, boolean secure,
String host, int port, INodeDriver driver) {
- super(userId, key, secure, host, port, driver);
+ super(userId, password, secure, host, port, driver);
}
public Map<String, String> addDefaultHeaders(Map<String, String> headers) {
headers.put("Accept", "text/xml");
- String authorization = "Basic " + new String(Base64.encodeBase64((userId + ":" + key).getBytes()));
+ String authorization = "Basic " + new String(Base64.encodeBase64((accessId + ":" + accessKey).getBytes()));
headers.put("Authorization", authorization);
headers.put("Content-Type", "text/xml");
return headers;
Modified: incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMDriver.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMDriver.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMDriver.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMDriver.java Fri Sep 3 15:43:12 2010
@@ -7,12 +7,11 @@ import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import base.ConnectionKey;
import base.Node;
import base.NodeDriver;
import base.NodeState;
+import base.Utils;
import base.beans.NodeAuth;
import base.beans.NodeImage;
import base.beans.NodeLocation;
@@ -25,11 +24,10 @@ import base.interfaces.IResponse;
* TODO: overload constructor with userId, key, host, and port
* TODO: listImages(NodeLocation)
* TODO: listSizes(NodeLocation)
+ * TODO: update to use XPath -- See Amazon EC2 Driver
*/
public class IBMDriver extends NodeDriver {
- private static final String NAME = "IBM Developer Cloud";
-
private static final String REST_BASE = "/computecloud/enterprise/api/rest/20100331";
private static final Map<Integer, NodeState> NODE_STATE_MAP = new HashMap<Integer, NodeState>();
@@ -55,11 +53,11 @@ public class IBMDriver extends NodeDrive
}
public String getName() {
- return NAME;
+ return "IBM Smart Business Development and Test Cloud";
}
public INode createNode(String name, NodeSize size, NodeImage image,
- NodeLocation location, NodeAuth auth, Map<String, String> extra) {
+ NodeLocation location, NodeAuth auth, Map<String, Object> extra) {
// Compose headers for message body
Map<String, String> data = new HashMap<String, String>();
data.put("name", name);
@@ -73,11 +71,11 @@ public class IBMDriver extends NodeDrive
}
if (extra != null) {
for (String key : extra.keySet()) {
- data.put(key, extra.get(key));
+ data.put(key, (String)extra.get(key));
}
}
- String encoded = ConnectionKey.urlEncodeMap(data);
+ String encoded = Utils.urlEncodeMap(data);
Map<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/x-www-form-urlencoded");
IResponse response = connection.request("POST", REST_BASE + "/instances", headers, null, encoded);
@@ -91,7 +89,7 @@ public class IBMDriver extends NodeDrive
Map<String, String> data = new HashMap<String, String>();
data.put("state", "restart");
IResponse response = connection.request("PUT", REST_BASE + "/instances/"
- + node.getId(), headers, null, ConnectionKey.urlEncodeMap(data));
+ + node.getId(), headers, null, Utils.urlEncodeMap(data));
new IBMHandler(response);
return response.getStatus() == 200;
}
@@ -106,22 +104,22 @@ public class IBMDriver extends NodeDrive
public List<NodeImage> listImages() {
IResponse response = connection.request("GET", REST_BASE + "/offerings/image",
null, null, "");
- IBMHandler rh = new IBMHandler(response);
- return parseImages((Document) rh.getParsedObject());
+ IBMHandler handler = new IBMHandler(response);
+ return parseImages((Document)handler.getParsedObject());
}
public List<NodeLocation> listLocations() {
IResponse response = connection.request("GET", REST_BASE + "/locations",
null, null, "");
- IBMHandler rh = new IBMHandler(response);
- return parseLocations((Document) rh.getParsedObject());
+ IBMHandler handler = new IBMHandler(response);
+ return parseLocations((Document)handler.getParsedObject());
}
public List<INode> listNodes() {
IResponse response = connection.request("GET", REST_BASE + "/instances",
null, null, "");
- IBMHandler rh = new IBMHandler(response);
- return parseNodes((Document) rh.getParsedObject());
+ IBMHandler handler = new IBMHandler(response);
+ return parseNodes((Document)handler.getParsedObject());
}
public List<NodeSize> listSizes() {
@@ -140,7 +138,7 @@ public class IBMDriver extends NodeDrive
private List<NodeImage> parseImages(Document doc) {
List<NodeImage> images = new ArrayList<NodeImage>();
- List<Element> elems = getFirstElementsByTagName(doc
+ List<Element> elems = Utils.getFirstElementsByTagName(doc
.getDocumentElement(), "Image");
for (Element elem : elems) {
images.add(parseImage(elem));
@@ -149,14 +147,15 @@ public class IBMDriver extends NodeDrive
}
private NodeImage parseImage(Element elem) {
- return new NodeImage(getTextValue(elem, "ID"), getTextValue(elem,
- "Name"), null, // TODO: include parametersUrl in extra
+ return new NodeImage(Utils.getTextValue(elem, "ID"),
+ Utils.getTextValue(elem, "Name"),
+ null, // TODO: include parametersUrl in extra
this);
}
private List<INode> parseNodes(Document doc) {
List<INode> nodes = new ArrayList<INode>();
- List<Element> elems = getFirstElementsByTagName(doc.getDocumentElement(), "Instance");
+ List<Element> elems = Utils.getFirstElementsByTagName(doc.getDocumentElement(), "Instance");
for (Element elem : elems) {
nodes.add(parseNode(elem));
}
@@ -164,10 +163,10 @@ public class IBMDriver extends NodeDrive
}
private INode parseNode(Element elem) {
- return new Node(getTextValue(elem, "ID"),
- getTextValue(elem, "Name"),
- NODE_STATE_MAP.get(new Integer(getTextValue(elem, "Status"))),
- getTextValue(elem, "IP"),
+ return new Node(Utils.getTextValue(elem, "ID"),
+ Utils.getTextValue(elem, "Name"),
+ NODE_STATE_MAP.get(new Integer(Utils.getTextValue(elem, "Status"))),
+ Utils.getTextValue(elem, "IP"),
null,
null,
this);
@@ -175,7 +174,7 @@ public class IBMDriver extends NodeDrive
private List<NodeLocation> parseLocations(Document doc) {
List<NodeLocation> locations = new ArrayList<NodeLocation>();
- List<Element> elems = getFirstElementsByTagName(doc
+ List<Element> elems = Utils.getFirstElementsByTagName(doc
.getDocumentElement(), "Location");
for (Element elem : elems) {
locations.add(parseLocation(elem));
@@ -184,41 +183,7 @@ public class IBMDriver extends NodeDrive
}
private NodeLocation parseLocation(Element elem) {
- return new NodeLocation(getTextValue(elem, "ID"), getTextValue(elem,
+ return new NodeLocation(Utils.getTextValue(elem, "ID"), Utils.getTextValue(elem,
"Name"), "US", this);
}
-
- private String getTextValue(Element elem, String tagName) {
- NodeList nl = elem.getElementsByTagName(tagName);
- if (nl.getLength() > 0) {
- if (nl.item(0).getFirstChild() == null) {
- return "";
- } else {
- return nl.item(0).getFirstChild().getNodeValue();
- }
- } else {
- return null;
- }
- }
-
- private List<Element> getFirstElementsByTagName(Element elem, String tagName) {
- List<Element> elements = new ArrayList<Element>();
- NodeList children = elem.getChildNodes();
- for (int i = 0; i < children.getLength(); i++) {
- Element child = (Element) children.item(i);
- if (child.getTagName().equals(tagName)) {
- elements.add(child);
- }
- }
- return elements;
- }
- //
- // private List<String> getTextValues(Element elem, String tagName) {
- // List<String> values = new ArrayList<String>();
- // NodeList nl = elem.getElementsByTagName(tagName);
- // for (int i = 0; i < nl.getLength(); i++) {
- // values.add(nl.item(i).getFirstChild().getNodeValue());
- // }
- // return values;
- // }
}
Modified: incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMHandler.java
URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMHandler.java?rev=992334&r1=992333&r2=992334&view=diff
==============================================================================
--- incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMHandler.java (original)
+++ incubator/libcloud/sandbox/java/trunk/src/drivers/ibm/IBMHandler.java Fri Sep 3 15:43:12 2010
@@ -10,11 +10,11 @@ import javax.xml.parsers.ParserConfigura
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
-import base.DefaultHandler;
+import base.ResponseHandler;
import base.exceptions.InvalidCredsException;
import base.interfaces.IResponse;
-public class IBMHandler extends DefaultHandler {
+public class IBMHandler extends ResponseHandler {
public IBMHandler(IResponse response) {
super(response);