From libcloud-commits-return-518-apmail-incubator-libcloud-commits-archive=incubator.apache.org@incubator.apache.org Tue Sep 14 21:57:29 2010 Return-Path: Delivered-To: apmail-incubator-libcloud-commits-archive@minotaur.apache.org Received: (qmail 9188 invoked from network); 14 Sep 2010 21:57:29 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 14 Sep 2010 21:57:29 -0000 Received: (qmail 29970 invoked by uid 500); 14 Sep 2010 21:57:29 -0000 Delivered-To: apmail-incubator-libcloud-commits-archive@incubator.apache.org Received: (qmail 29943 invoked by uid 500); 14 Sep 2010 21:57:29 -0000 Mailing-List: contact libcloud-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: libcloud@incubator.apache.org Delivered-To: mailing list libcloud-commits@incubator.apache.org Received: (qmail 29934 invoked by uid 99); 14 Sep 2010 21:57:29 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 14 Sep 2010 21:57:29 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 14 Sep 2010 21:57:24 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id EA90823889B9; Tue, 14 Sep 2010 21:57:03 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r997113 [1/2] - in /incubator/libcloud/sandbox/java/trunk/src: ./ base/ base/connection/ base/interfaces/ libcloud/ libcloud/data/ libcloud/exceptions/ libcloud/interfaces/ libcloud/providers/ libcloud/providers/amazon/ libcloud/providers/i... Date: Tue, 14 Sep 2010 21:57:03 -0000 To: libcloud-commits@incubator.apache.org From: woodser@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100914215703.EA90823889B9@eris.apache.org> Author: woodser Date: Tue Sep 14 21:57:01 2010 New Revision: 997113 URL: http://svn.apache.org/viewvc?rev=997113&view=rev Log: - Rackspace driver added. - Refactored structure for simplecloud. - Miscellaneous fixes & enhancements. Added: incubator/libcloud/sandbox/java/trunk/src/Example.java incubator/libcloud/sandbox/java/trunk/src/base/ incubator/libcloud/sandbox/java/trunk/src/base/Driver.java incubator/libcloud/sandbox/java/trunk/src/base/connection/ incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java (with props) incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java (with props) incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java (with props) incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java (with props) incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java (with props) incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java (with props) incubator/libcloud/sandbox/java/trunk/src/base/interfaces/ incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java (with props) incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/ incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/data/ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/ incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/ incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2APSEDriver.java incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Connection.java incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Driver.java incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2EUWestDriver.java incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Handler.java incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USEastDriver.java incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USWestDriver.java incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/rackspace/ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/rackspace/RackspaceConnection.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/rackspace/RackspaceDriver.java (with props) incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/rackspace/RackspaceHandler.java (with props) incubator/libcloud/sandbox/java/trunk/src/simplecloud/ incubator/libcloud/sandbox/java/trunk/src/simplecloud/document/ incubator/libcloud/sandbox/java/trunk/src/simplecloud/queue/ incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/ incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/StorageAdapter.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/StorageFactory.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/data/ incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/data/File.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/data/Folder.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/data/Item.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/exceptions/ incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/exceptions/StorageException.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/interfaces/ incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/interfaces/IStorageAdapter.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/ incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/ incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/Main.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Adapter.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Connection.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/amazon/S3Handler.java incubator/libcloud/sandbox/java/trunk/src/simplecloud/storage/providers/nirvanix/ Added: incubator/libcloud/sandbox/java/trunk/src/Example.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/Example.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/Example.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/Example.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,55 @@ + + +import java.util.ArrayList; +import java.util.List; + +import libcloud.DriverFactory; +import libcloud.NodeDriver; +import libcloud.DriverFactory.Provider; +import libcloud.data.NodeImage; +import libcloud.data.NodeLocation; +import libcloud.data.NodeSize; +import libcloud.interfaces.INode; +import libcloud.providers.amazon.EC2USEastDriver; +import libcloud.providers.ibm.IBMDriver; +import libcloud.providers.rackspace.RackspaceDriver; + +/* + * Illustrates how to interact with multiple cloud providers using a common + * interface using Apache libcloud. + */ +public class Example { + + /* + * Entry point of execution. + */ + public static void main(String[] args) { + // Fetch driver(s). + Class ibmClass = DriverFactory.getDriver(Provider.IBM); + IBMDriver ibmDriver = (IBMDriver)DriverFactory.constructDriver(ibmClass, "username", "password"); + Class ec2USEastClass = DriverFactory.getDriver(Provider.EC2_US_EAST); + EC2USEastDriver ec2USEastDriver = (EC2USEastDriver)DriverFactory.constructDriver(ec2USEastClass, "access key id", "access key"); + Class rackspaceClass = DriverFactory.getDriver(Provider.RACKSPACE); + RackspaceDriver rackspaceDriver = (RackspaceDriver)DriverFactory.constructDriver(rackspaceClass, "your username", "your api key"); + + // Insert driver(s) into array for generic processing. + List drivers = new ArrayList(); + drivers.add(ibmDriver); + drivers.add(ec2USEastDriver); + drivers.add(rackspaceDriver); + + // Process drivers. + for (NodeDriver driver : drivers) { + System.out.println(driver.getName() + ':'); + List nodes = driver.listNodes(); + List images = driver.listImages(); + List sizes = driver.listSizes(); + List 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/base/Driver.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/Driver.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/base/Driver.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/base/Driver.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,8 @@ +package base; + +import base.interfaces.IConnection; + +public class Driver { + + protected IConnection connection; +} Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,212 @@ +package base.connection; + +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 java.util.TreeSet; + +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +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.Driver; +import base.interfaces.IConnection; + +/* + * Manages a connection with a secret access key. + */ +public abstract class ConnectionKey implements IConnection { + + protected String host; + + protected int port; + + protected String accessId; + + protected String accessKey; + + protected boolean secure; + + protected Driver driver; + + protected String method; + + protected String path; + + protected DefaultHttpClient httpClient; + + protected HttpHost httpHost; + + public ConnectionKey(String accessKey, boolean secure, String host, Driver driver) { + this.accessKey = accessKey; + this.secure = secure; + this.host = host; + this.driver = driver; + this.accessId = null; // subclass may initialize + this.port = -1; // default port used by HTTPComponents + this.path = null; + } + + public ConnectionKey(String accessKey, boolean secure, String host, int port, + Driver driver) { + this.accessKey = accessKey; + this.secure = secure; + this.host = host; + this.port = port; + this.driver = driver; + this.httpClient = null; + this.httpHost = null; + this.accessId = null; // subclass may initialize + this.path = null; + } + + public void connect() { + connect(host, port); + } + + public void connect(String host, int port) { + this.host = host; + this.port = port; + + httpClient = new DefaultHttpClient(); + if (accessId != null) { + httpClient.getCredentialsProvider().setCredentials( + new AuthScope(host, port), + new UsernamePasswordCredentials(accessId, accessKey)); + } + } + + public Response request(String method, String path, + Map headers, Map params, String data) { + this.method = method; + this.path = path; + + // Connect if not already connected + if (httpClient == null) { + connect(); + } + + // Compose request headers with priority + Map reqHeaders = new HashMap(); + reqHeaders.put("User-Agent", getUserAgent()); // 3: libcloud headers + reqHeaders.put("Host", host); + if (headers != null) reqHeaders.putAll(headers); // 2: argument headers + reqHeaders = addDefaultHeaders(reqHeaders); // 1: provider headers + + // Compose request parameters with priority + Map reqParams = (params != null ? params // 2: argument parameters + : new HashMap()); + reqParams = addDefaultParams(reqParams); // 1: provider parameters + + // Create URI endpoint + URI uri = null; + try { + String protocol = secure ? "https" : "http"; + uri = URIUtils.createURI(protocol, host, port, path, urlEncodeMap(reqParams), null); + } catch (URISyntaxException e) { + e.printStackTrace(); + return null; + } + + // Create request to send + HttpUriRequest request = null; + if (method.equalsIgnoreCase("GET")) { + request = new HttpGet(uri); + } else if (method.equalsIgnoreCase("DELETE")) { + request = new HttpDelete(uri); + } else if (method.equalsIgnoreCase("PUT")) { + request = new HttpPut(uri); + } else if (method.equalsIgnoreCase("POST")) { + request = new HttpPost(uri); + } else { + throw new IllegalArgumentException("Illegal HTTP method: " + method); + } + + // Encode and add the payload data + String encoded = encodeData(data); + if (encoded != null && !encoded.equals("")) { + try { + ((HttpEntityEnclosingRequest) request).setEntity(new StringEntity(encoded)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return null; + } + } + + // Add headers to the request + for (String header : reqHeaders.keySet()) { + request.addHeader(header, reqHeaders.get(header)); + } + + // Execute the request! + try { + return new Response(httpClient.execute(request)); + } catch (ClientProtocolException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; // Error + } + + /* + * 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 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 map) { + if (map == null) return null; + + // Convert map to List for URLEncodedUtils + List nvp = new ArrayList(); + for (String key : new TreeSet(map.keySet())) { // preserve order + nvp.add(new BasicNameValuePair(key, map.get(key))); + } + return URLEncodedUtils.format(nvp, "UTF-8"); + } + + // ============================ PROTECTED METHODS =========================== + protected Map addDefaultHeaders(Map headers) { + return headers; + } + + protected Map addDefaultParams(Map params) { + return params; + } + + protected String encodeData(String data) { + return data; + } + + // ============================ PRIVATE METHODS =========================== + /* + * Defines the user agent used when making requests. + * + * @return String is the user agent for making requests + */ + private String getUserAgent() { + return "libcloud-java"; // TODO: generate version like python? + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionKey.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,18 @@ +package base.connection; + +import base.Driver; + +public class ConnectionUserAndKey extends ConnectionKey { + + public ConnectionUserAndKey(String accessId, String accessKey, boolean secure, + String host, int port, Driver driver) { + super(accessKey, secure, host, port, driver); + this.accessId = accessId; + } + + public ConnectionUserAndKey(String accessId, String accessKey, boolean secure, + String host, Driver driver) { + super(accessKey, secure, host, driver); + this.accessId = accessId; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/ConnectionUserAndKey.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,60 @@ +package base.connection; + +import java.util.Map; + +import base.Driver; + +public class LoggingConnection extends ConnectionKey { + + protected StringBuffer log; + + public LoggingConnection(String key, boolean secure, String host, int port, + Driver driver) { + super(key, secure, host, port, driver); + log = new StringBuffer(); + } + + public Response request(String method, String action, + Map headers, Map params, String data) { + log.append(logCurl(method, action, data, headers)); + Response response = super.request(method, action, headers, params, data); + log.append(logResponse(response)); + return response; + } + + protected String logResponse(Response response) { + String logEntry = "# -------- begin response ----------\n"; + logEntry += response.version.getProtocol() + "/" + + response.version.getMajor() + "." + response.version.getMinor(); + logEntry += " " + response.status + " " + response.phrase + "\r\n"; + + if (response.headers != null) { + for (Map.Entry header : response.headers.entrySet()) { + logEntry += header.getKey() + ": " + header.getValue() + "\r\n"; + } + } + + logEntry += "\r\n" + response.body + "\r\n"; + logEntry += "\n# -------- end response ------------\n"; + + return logEntry; + } + + protected String logCurl(String method, String url, String body, Map headers) { + String curl = "curl -X " + method + " "; + + if (headers != null) { + for (Map.Entry header : headers.entrySet()) { + curl += "-H \"" + header.getKey() + ": " + header.getValue() + "\" "; + } + } + + if (body != null && !"".equals(body)) { + curl += "-d \"" + body + "\" "; + } + + curl += url; + return curl; + } + +} Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnection.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,12 @@ +package base.connection; + +import base.Driver; + +public class LoggingConnectionUserAndKey extends LoggingConnection { + + public LoggingConnectionUserAndKey(String accessId, String accessKey, boolean secure, + String host, int port, Driver driver) { + super(accessKey, secure, host, port, driver); + this.accessId = accessId; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/LoggingConnectionUserAndKey.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,96 @@ +package base.connection; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.ProtocolVersion; + +import base.interfaces.IResponse; + + +public class Response implements IResponse { + + protected int status; + + protected String phrase; + + protected String body; + + protected ProtocolVersion version; + + protected Map headers; + + public Response(HttpResponse response) { + + // Retrieve HTTP version from response + version = response.getStatusLine().getProtocolVersion(); + + // Retrieve status code from response + status = response.getStatusLine().getStatusCode(); + + // Retrieve reason from response + phrase = response.getStatusLine().getReasonPhrase(); + + // Retrieve body from response + body = null; + HttpEntity entity = response.getEntity(); + if (entity != null) { + try { + String line = null; + StringBuffer bodySb = new StringBuffer(); + BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent())); + while ((line = reader.readLine()) != null) { + bodySb.append(line); + } + body = bodySb.toString(); + entity.consumeContent(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + + // Retrieve headers from response + headers = new HashMap(); + for (Header header : response.getAllHeaders()) { + this.headers.put(header.getName(), header.getValue()); + } + } + + public String getBody() { + return body; + } + + public ProtocolVersion getVersion() { + return version; + } + + public String getPhrase() { + return phrase; + } + + public Map getHeaders() { + return headers; + } + + public int getStatus() { + return status; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(status + " " + phrase + '\n'); + sb.append("Headers:\n"); + for (String key : headers.keySet()) { + sb.append('\t' + key + ": " + headers.get(key) + '\n'); + } + sb.append("Body: "); + sb.append(body); + return sb.toString(); + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/Response.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,75 @@ +package base.connection; + +import base.interfaces.IResponse; + +/* + * Default handler for request responses. Subclasses should extend for custom + * processing. + */ +public class ResponseHandler { + + protected IResponse response; + + protected Object object; + + /* + * Constructs the handler with the given response. + * + * @param response is the request's response + */ + public ResponseHandler(IResponse response) { + this.response = response; + + if (success()) { + parseBody(); + } else { + throw new RuntimeException(parseError()); + } + } + + /* + * 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; + } + + /* + * 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 && response.getStatus() <= 299; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/base/connection/ResponseHandler.java ------------------------------------------------------------------------------ svn:executable = * Added: 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=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,15 @@ +package base.interfaces; + +import java.util.Map; + +import base.connection.Response; + +public interface IConnection { + + public void connect(); + + public void connect(String host, int port); + + public Response request(String method, String action, + Map headers, Map params, String data); +} Propchange: incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IConnection.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,14 @@ +package base.interfaces; + +import java.util.Map; + +public interface IResponse { + + public int getStatus(); + + public String getBody(); + + public String getPhrase(); + + public Map getHeaders(); +} Propchange: incubator/libcloud/sandbox/java/trunk/src/base/interfaces/IResponse.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,128 @@ +package libcloud; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.EnumMap; + +/* + * Manages provider information and provides a driver factory. + */ +public class DriverFactory { + + // Maps providers to the driver packages. + private static EnumMap providerMap; + + /* + * List of available drivers. + */ + public static enum Provider { + DUMMY, + EC2_US_EAST, + EC2_US_WEST, + EC2_EU_WEST, + EC2_AP_SOUTHEAST, + ECP, + GOGRID, + RACKSPACE, + SLICEHOST, + VPSNET, + LINODE, + RIMUHOSTING, + VOXEL, + SOFTLAYER, + EUCALYPTUS, + IBM, + OPENNEBULA, + DREAMHOST; + } + + /* + * Initializes the map bewteen providers (enum) and their driver packages. + */ + private static void initProviderMap() + { + providerMap = new EnumMap(Provider.class); + + //First parameter to the map is the Provider name from the enum, the + //second parameter is the package name of the driver. When adding a new + //provider, simply add it to the "Provider" enum and add a providerMap.put + //below with the appropriate parameters. + providerMap.put(Provider.IBM, "libcloud.providers.ibm.IBMDriver"); + providerMap.put(Provider.RACKSPACE, "libcloud.providers.rackspace.XXX"); + providerMap.put(Provider.SLICEHOST, "libcloud.providers.slicehost.XXX"); + providerMap.put(Provider.EC2_US_EAST, "libcloud.providers.amazon.EC2USEastDriver"); + providerMap.put(Provider.EC2_EU_WEST, "libcloud.providers.amazon.EC2EUWestDriver"); + providerMap.put(Provider.EC2_US_WEST, "libcloud.providers.amazon.EC2USWestDriver"); + providerMap.put(Provider.EC2_AP_SOUTHEAST, "libcloud.providers.amazon.EC2APSoutheastDriver"); + providerMap.put(Provider.ECP, ""); + providerMap.put(Provider.GOGRID, ""); + providerMap.put(Provider.VPSNET, ""); + providerMap.put(Provider.LINODE, ""); + providerMap.put(Provider.RIMUHOSTING, ""); + providerMap.put(Provider.VOXEL, ""); + providerMap.put(Provider.SOFTLAYER, ""); + providerMap.put(Provider.EUCALYPTUS, ""); + providerMap.put(Provider.OPENNEBULA, ""); + providerMap.put(Provider.DREAMHOST, ""); + } + + /* + * Retrieves the driver for the given provider. + * + * @param p defines the provider to retrieve the driver for + * + * @return Class is the provider's corresponding driver class + */ + @SuppressWarnings("unchecked") + public static Class getDriver(Provider p) + { + if (providerMap == null) + initProviderMap(); + + @SuppressWarnings("rawtypes") + Class driverClass = null; + try { + String classname = providerMap.get(p); + driverClass = Class.forName(classname).asSubclass(NodeDriver.class); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return driverClass; + } + + /* + * Constructs a driver from the given driver class and constructor arguments. + * + * @param driverClass is the class of the driver to construct + * @param args are the arguments to the driver's constructor + * + * @return NodeDriver is the initialized driver. Typecast this to the specific driver type. + */ + public static NodeDriver constructDriver(Class driverClass, Object ... args) { + // Convert arguments to class array + Class[] classArgs = new Class[args.length]; + for (int i = 0; i < args.length; i++) { + classArgs[i] = args[i].getClass(); + } + + try { + // Get constructor and create instance + Constructor constructor = driverClass.getConstructor(classArgs); + return (NodeDriver)constructor.newInstance(args); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + + return null; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/DriverFactory.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,8 @@ +package libcloud; + +import libcloud.interfaces.INodeDriver; +import base.Driver; + +public abstract class NodeDriver extends Driver implements INodeDriver { + +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/NodeDriver.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,85 @@ +package libcloud.data; + +import java.util.Map; +import java.util.UUID; + +import libcloud.interfaces.INode; +import libcloud.interfaces.INodeDriver; + +public class Node implements INode { + + private String id; + + private String name; + + private NodeState state; + + private String publicIp; + + private String privateIp; + + private Map extra; + + private INodeDriver driver; + + public Node(String id, String name, NodeState state, String publicIp, String privateIp, Map extra, INodeDriver driver) { + this.id = id; + this.name = name; + this.state = state; + this.publicIp = publicIp; + this.privateIp = privateIp; + this.extra = extra; + this.driver = driver; + } + + public boolean destroy() { + return driver.destroyNode(this); + } + + public boolean reboot() { + return driver.rebootNode(this); + } + + public INodeDriver getDriver() { + return driver; + } + + public Map getExtra() { + return extra; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getPrivateIp() { + return privateIp; + } + + public String getPublicIp() { + return publicIp; + } + + public NodeState getState() { + return state; + } + + public String getUuid() { + return UUID.randomUUID().toString(); + } + + public String toString() { + return ""; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/Node.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,10 @@ +package libcloud.data; + +public class NodeAuth { + + public String secret; + + public NodeAuth(String secret) { + this.secret = secret; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeAuth.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,31 @@ +package libcloud.data; + +import java.util.Map; + +import libcloud.interfaces.INodeDriver; + +public class NodeImage { + + public String id; + + public String name; + + public Map extra; + + public INodeDriver driver; + + public NodeImage(String id, String name, Map extra, INodeDriver driver) { + this.id = id; + this.name = name; + this.extra = extra; + this.driver = driver; + } + + public String toString() { + return ""; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeImage.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,30 @@ +package libcloud.data; + +import libcloud.interfaces.INodeDriver; + +public class NodeLocation { + + public String id; + + public String name; + + public String country; + + public INodeDriver driver; + + public NodeLocation(String id, String name, String country, INodeDriver driver) { + this.id = id; + this.name = name; + this.country = country; + this.driver = driver; + } + + public String toString() { + return ""; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeLocation.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,43 @@ +package libcloud.data; + +import libcloud.interfaces.INodeDriver; + +public class NodeSize { + + public String id; + + public String name; + + public int ram; + + public int disk; + + public int bandwidth; + + public float price; + + public INodeDriver driver; + + public NodeSize(String id, String name, int ram, int disk, int bandwidth, + float price, INodeDriver driver) { + this.id = id; + this.name = name; + this.ram = ram; + this.disk = disk; + this.bandwidth = bandwidth; + this.price = price; + this.driver = driver; + } + + public String toString() { + return ""; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeSize.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,9 @@ +package libcloud.data; + +public enum NodeState { + RUNNING, + REBOOTING, + TERMINATED, + PENDING, + UNKNOWN; +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/data/NodeState.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,14 @@ +package libcloud.exceptions; + +public class InvalidCredsException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public InvalidCredsException() { + super(); + } + + public InvalidCredsException(String msg) { + super(msg); + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/exceptions/InvalidCredsException.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,28 @@ +package libcloud.interfaces; + +import java.util.Map; + +import libcloud.data.NodeState; + +public interface INode { + + public boolean reboot(); + + public boolean destroy(); + + public String getUuid(); + + public String getId(); + + public String getName(); + + public NodeState getState(); + + public String getPublicIp(); + + public String getPrivateIp(); + + public INodeDriver getDriver(); + + public Map getExtra(); +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INode.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,30 @@ +package libcloud.interfaces; + +import java.util.List; +import java.util.Map; + +import libcloud.data.NodeAuth; +import libcloud.data.NodeImage; +import libcloud.data.NodeLocation; +import libcloud.data.NodeSize; + +public interface INodeDriver { + + public INode createNode(String name, NodeSize size, + NodeImage image, NodeLocation location, NodeAuth auth, + Map extra); + + public boolean destroyNode(INode node); + + public boolean rebootNode(INode node); + + public List listNodes(); + + public List listImages(); + + public List listSizes(); + + public List listLocations(); + + public String getName(); +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/interfaces/INodeDriver.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2APSEDriver.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2APSEDriver.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2APSEDriver.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2APSEDriver.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,46 @@ +package libcloud.providers.amazon; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import libcloud.data.NodeLocation; + +public class EC2APSEDriver extends EC2Driver { + + private static final String EC2_AP_SE_HOST = "ec2.ap-southeast-1.amazonaws.com"; + + private static final Map EC2_AP_SE_PRICES = initNodePrices(); + + public EC2APSEDriver(String accessId, String accessKey) { + super(accessId, accessKey, EC2_AP_SE_HOST); + } + + public List listLocations() { + List locations = new ArrayList(); + 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 initNodePrices() { + Map prices = new HashMap(); + 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/libcloud/providers/amazon/EC2Connection.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Connection.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Connection.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Connection.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,77 @@ +package libcloud.providers.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.Driver; +import base.connection.ConnectionKey; +import base.connection.ConnectionUserAndKey; + +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, + Driver driver) { + super(accessId, accessKey, DEFAULT_SECURE, host, driver); + } + + protected Map addDefaultParams(Map 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, path)); + 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 params, String accessKey, String path) { + // Sort the parameters by key + TreeSet sortedKeys = new TreeSet(params.keySet()); + Map sortedParams = new HashMap(); + for (String key : sortedKeys){ + sortedParams.put(key, params.get(key)); + } + + // Generate stringToSign + String qs = ConnectionKey.urlEncodeMap(sortedParams); + qs = qs.replace("+", "%20"); + String stringToSign = this.method + '\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/libcloud/providers/amazon/EC2Driver.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Driver.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Driver.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Driver.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,404 @@ +package libcloud.providers.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 libcloud.NodeDriver; +import libcloud.data.Node; +import libcloud.data.NodeAuth; +import libcloud.data.NodeImage; +import libcloud.data.NodeLocation; +import libcloud.data.NodeSize; +import libcloud.data.NodeState; +import libcloud.interfaces.INode; + +import org.apache.commons.codec.binary.Base64; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +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 NODE_SIZES = initNodeSizes(); + private static final Map NODE_STATE_MAP = new HashMap(); + + /* + * 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 extra) { + // Add base parameters + Map params = new HashMap(); + 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 groups = null; + if (securityGroup instanceof List) { + groups = (List)securityGroup; + } else { + groups = new ArrayList(); + 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 params = new HashMap(); + 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 params = new HashMap(); + 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 listNodes() { + Map params = new HashMap(); + 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 listImages() { + Map params = new HashMap(); + params.put("Action", "DescribeImages"); + IResponse response = connection.request("GET", "/", null, params, null); + EC2Handler handler = new EC2Handler(response); + return parseImages((Document)handler.getParsedObject()); + } + + public List listSizes() { + List sizes = new ArrayList(); + 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 params = new HashMap(); + 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 is a list of parsed objects as defined & handled by EC2Handler + */ + public List exAuthorizeSecurityGroupPermissive(String name) { + List results = new ArrayList(); + + // Request 1 + Map params = new HashMap(); + 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 parseNodesByGroup(Element elem) { + try { + List nodes = new ArrayList(); + 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 groups = new ArrayList(); + 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 parseNodes(Element elem, String path, List groups) { + try { + List nodes = new ArrayList(); + 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 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 extra = new HashMap(); + 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 productCodes = new ArrayList(); + 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 parseImages(Document doc) { + List images = new ArrayList(); + 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 are parameters for the AWS query + */ + private Map pathList(String key, String[] values) { + Map params = new HashMap(); + 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 initNodeSizes() { + Map sizes = new HashMap(); + 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/libcloud/providers/amazon/EC2EUWestDriver.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2EUWestDriver.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2EUWestDriver.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2EUWestDriver.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,46 @@ +package libcloud.providers.amazon; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import libcloud.data.NodeLocation; + +public class EC2EUWestDriver extends EC2Driver { + + private static final String EC2_EU_WEST_HOST = "ec2.eu-west-1.amazonaws.com"; + + private static final Map EC2_EU_WEST_PRICES = initNodePrices(); + + public EC2EUWestDriver(String accessId, String accessKey) { + super(accessId, accessKey, EC2_EU_WEST_HOST); + } + + public List listLocations() { + List locations = new ArrayList(); + 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 initNodePrices() { + Map prices = new HashMap(); + 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/libcloud/providers/amazon/EC2Handler.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Handler.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Handler.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2Handler.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,83 @@ +package libcloud.providers.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 libcloud.exceptions.InvalidCredsException; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import base.connection.ResponseHandler; +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/libcloud/providers/amazon/EC2USEastDriver.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USEastDriver.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USEastDriver.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USEastDriver.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,46 @@ +package libcloud.providers.amazon; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import libcloud.data.NodeLocation; + +public class EC2USEastDriver extends EC2Driver { + + private static final String EC2_US_EAST_HOST = "ec2.us-east-1.amazonaws.com"; + + private static final Map EC2_US_EAST_PRICES = initNodePrices(); + + public EC2USEastDriver(String accessId, String accessKey) { + super(accessId, accessKey, EC2_US_EAST_HOST); + } + + public List listLocations() { + List locations = new ArrayList(); + 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 initNodePrices() { + Map prices = new HashMap(); + 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/libcloud/providers/amazon/EC2USWestDriver.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USWestDriver.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USWestDriver.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/amazon/EC2USWestDriver.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,46 @@ +package libcloud.providers.amazon; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import libcloud.data.NodeLocation; + +public class EC2USWestDriver extends EC2Driver { + + private static final String EC2_US_WEST_HOST = "ec2.us-west-1.amazonaws.com"; + + private static final Map EC2_US_WEST_PRICES = initNodePrices(); + + public EC2USWestDriver(String accessId, String accessKey) { + super(accessId, accessKey, EC2_US_WEST_HOST); + } + + public List listLocations() { + List locations = new ArrayList(); + 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 initNodePrices() { + Map prices = new HashMap(); + 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/libcloud/providers/ibm/IBMConnection.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,32 @@ +package libcloud.providers.ibm; + +import java.util.Map; + +import libcloud.NodeDriver; + +import org.apache.commons.codec.binary.Base64; + +import base.connection.ConnectionUserAndKey; + +public class IBMConnection extends ConnectionUserAndKey { + + private static final String DEFAULT_HOST = "www-147.ibm.com"; + private static final boolean DEFAULT_SECURE = true; + + public IBMConnection(String userId, String key, NodeDriver driver) { + super(userId, key, DEFAULT_SECURE, DEFAULT_HOST, driver); + } + + public IBMConnection(String userId, String password, boolean secure, + String host, int port, NodeDriver driver) { + super(userId, password, secure, host, port, driver); + } + + protected Map addDefaultHeaders(Map headers) { + headers.put("Accept", "text/xml"); + String authorization = "Basic " + new String(Base64.encodeBase64((accessId + ":" + accessKey).getBytes())); + headers.put("Authorization", authorization); + headers.put("Content-Type", "text/xml"); + return headers; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMConnection.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,229 @@ +package libcloud.providers.ibm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import libcloud.NodeDriver; +import libcloud.data.Node; +import libcloud.data.NodeAuth; +import libcloud.data.NodeImage; +import libcloud.data.NodeLocation; +import libcloud.data.NodeSize; +import libcloud.data.NodeState; +import libcloud.interfaces.INode; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import base.connection.ConnectionKey; +import base.interfaces.IResponse; + +/* + * TODO: comment all classes + * 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 REST_BASE = "/computecloud/enterprise/api/rest/20100331"; + + private static final Map NODE_STATE_MAP = new HashMap(); + + public IBMDriver(String userId, String key) { + connection = new IBMConnection(userId, key, this); + + // Map IBM instance states to libcloud + NODE_STATE_MAP.put(0, NodeState.PENDING); + NODE_STATE_MAP.put(1, NodeState.PENDING); + NODE_STATE_MAP.put(2, NodeState.TERMINATED); + NODE_STATE_MAP.put(3, NodeState.TERMINATED); + NODE_STATE_MAP.put(4, NodeState.TERMINATED); + NODE_STATE_MAP.put(5, NodeState.RUNNING); + NODE_STATE_MAP.put(6, NodeState.UNKNOWN); + NODE_STATE_MAP.put(7, NodeState.PENDING); + NODE_STATE_MAP.put(8, NodeState.REBOOTING); + NODE_STATE_MAP.put(9, NodeState.PENDING); + NODE_STATE_MAP.put(10, NodeState.PENDING); + NODE_STATE_MAP.put(11, NodeState.TERMINATED); + NODE_STATE_MAP.put(12, NodeState.PENDING); // Deprovision pending + NODE_STATE_MAP.put(13, NodeState.PENDING); // Restart pending + } + + public String getName() { + return "IBM Smart Business Development and Test Cloud"; + } + + public INode createNode(String name, NodeSize size, NodeImage image, + NodeLocation location, NodeAuth auth, Map extra) { + // Compose headers for message body + Map data = new HashMap(); + data.put("name", name); + data.put("imageID", image.id); + data.put("instanceType", size.id); + if (location != null) { + data.put("location", location.id); + } + if (auth != null) { + data.put("publicKey", auth.secret); + } + if (extra != null) { + for (String key : extra.keySet()) { + data.put(key, (String)extra.get(key)); + } + } + + String encoded = ConnectionKey.urlEncodeMap(data); + Map headers = new HashMap(); + headers.put("Content-Type", "application/x-www-form-urlencoded"); + IResponse response = connection.request("POST", REST_BASE + "/instances", headers, null, encoded); + IBMHandler handler = new IBMHandler(response); + return parseNodes((Document)handler.getParsedObject()).get(0); + } + + public boolean rebootNode(INode node) { + Map headers = new HashMap(); + headers.put("Content-Type", "application/x-www-form-urlencoded"); + Map data = new HashMap(); + data.put("state", "restart"); + IResponse response = connection.request("PUT", REST_BASE + "/instances/" + node.getId(), headers, null, ConnectionKey.urlEncodeMap(data)); + new IBMHandler(response); + return response.getStatus() == 200; + } + + public boolean destroyNode(INode node) { + IResponse response = connection.request("DELETE", REST_BASE + "/instances/" + node.getId(), null, null, ""); + new IBMHandler(response); + return response.getStatus() == 200; + } + + public List listImages() { + IResponse response = connection.request("GET", REST_BASE + "/offerings/image", null, null, ""); + IBMHandler handler = new IBMHandler(response); + return parseImages((Document)handler.getParsedObject()); + } + + public List listLocations() { + IResponse response = connection.request("GET", REST_BASE + "/locations", null, null, ""); + IBMHandler handler = new IBMHandler(response); + return parseLocations((Document)handler.getParsedObject()); + } + + public List listNodes() { + IResponse response = connection.request("GET", REST_BASE + "/instances", null, null, ""); + IBMHandler handler = new IBMHandler(response); + return parseNodes((Document)handler.getParsedObject()); + } + + public List listSizes() { + List sizes = new ArrayList(); + sizes.add(new NodeSize("BRZ32.1/2048/175", "Bronze 32 bit", -1, -1, -1, -1, this)); + sizes.add(new NodeSize("BRZ64.2/4096/850", "Bronze 64 bit", -1, -1, -1, -1, this)); + sizes.add(new NodeSize("SLV32.2/4096/350", "Silver 32 bit", -1, -1, -1, -1, this)); + sizes.add(new NodeSize("SLV64.4/8192/1024", "Silver 64 bit", -1, -1, -1, -1, this)); + sizes.add(new NodeSize("GLD32.4/4096/350", "Bronze 32 bit", -1, -1, -1, -1, this)); + sizes.add(new NodeSize("GLD64.8/16384/1024", "Gold 64 bit", -1, -1, -1, -1, this)); + sizes.add(new NodeSize("PLT64.16/16384/2045", "Platinum 64 bit", -1, -1, -1, -1, this)); + return sizes; + } + + // ----------------------------- PRIVATE HELPERS --------------------------- + + private List parseImages(Document doc) { + List images = new ArrayList(); + List elems = getFirstElementsByTagName(doc + .getDocumentElement(), "Image"); + for (Element elem : elems) { + images.add(parseImage(elem)); + } + return images; + } + + private NodeImage parseImage(Element elem) { + return new NodeImage(getTextValue(elem, "ID"), + getTextValue(elem, "Name"), + null, // TODO: include parametersUrl in extra + this); + } + + private List parseNodes(Document doc) { + List nodes = new ArrayList(); + List elems = getFirstElementsByTagName(doc.getDocumentElement(), "Instance"); + for (Element elem : elems) { + nodes.add(parseNode(elem)); + } + return nodes; + } + + 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"), + null, + null, + this); + } + + private List parseLocations(Document doc) { + List locations = new ArrayList(); + List elems = getFirstElementsByTagName(doc + .getDocumentElement(), "Location"); + for (Element elem : elems) { + locations.add(parseLocation(elem)); + } + return locations; + } + + private NodeLocation parseLocation(Element elem) { + return new NodeLocation(getTextValue(elem, "ID"), getTextValue(elem, "Name"), "US", this); + } + + /* + * 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 is a list of immediate children matching tagName + */ + public static List getFirstElementsByTagName(Element elem, String tagName) { + List elements = new ArrayList(); + 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; + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMDriver.java ------------------------------------------------------------------------------ svn:executable = * Added: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java URL: http://svn.apache.org/viewvc/incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java?rev=997113&view=auto ============================================================================== --- incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java (added) +++ incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java Tue Sep 14 21:57:01 2010 @@ -0,0 +1,51 @@ +package libcloud.providers.ibm; + +import java.io.IOException; +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import libcloud.exceptions.InvalidCredsException; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import base.connection.ResponseHandler; +import base.interfaces.IResponse; + +public class IBMHandler extends ResponseHandler { + + public IBMHandler(IResponse response) { + super(response); + } + + protected void parseBody() { + object = null; + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + try { + 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() { + if (response.getStatus() == 401) { + if (response.getBody().equals("")) { + throw new InvalidCredsException(response.getStatus() + ": " + + response.getPhrase()); + } else { + throw new InvalidCredsException(response.getBody()); + } + } else { + return (String)response.getBody(); + } + } +} Propchange: incubator/libcloud/sandbox/java/trunk/src/libcloud/providers/ibm/IBMHandler.java ------------------------------------------------------------------------------ svn:executable = *