The research done for this post was conducted by the Rackspace Cloud development team.
When we released our Cloud Servers API a year ago, we wanted to adhere as strictly as possible to RESTful practice. We stuck to open, accepted web standards that existed to help take the guesswork out of the developer workload. We didn’t want to invent anything new but rather build things on well-defined standards. To share what we designed and to foster a more open cloud, we open sourced our Cloud Servers and Cloud Files API specifications under the Creative Commons 3.0 Attribution license – this is our commitment to having an open cloud.
With that being said, sometimes it’s easier to understand the benefits of one API versus another by detailing out the differences. Rackspace Cloud Servers and Amazon EC2 are credited to be the most widely used cloud computing providers and we both have API’s, some similarities but mostly differences. In particular, EC2 has a number of features not currently available in Cloud Servers – the ability to upload an image, for example. Likewise, there are certain features on Cloud Servers that are not available on EC2 – the ability to schedule automated backups, for example, or server persistence after a shutdown. At their heart, however, both services offer a standard set of features:
The purpose of this post is to provide a comparison of how this set of common features is exposed in the Cloud Servers and EC2 APIs.
The Cloud Servers API is truly RESTful. It makes very good use of the HTTP protocol. Every resource in the API (server, image, flavor) is identified by a unique URI. The interface to the API is based on the uniform subset of HTTP operations (GET, POST, PUT, DELETE) on these URIs. In contrast EC2 supports two APIs: a SOAP based API which is strictly RPC and a Query API. While the Query API supports REST-like queries it is not truly RESTful because it does not contain a uniform interface, instead of the uniform HTTP operations (GET, POST, PUT,..) it supports an arbitrary vocabulary of verbs (DescribeImages, DescribeInstances, CreateSnapshot, DeleteSnapshot). Additionally, all HTTP requests on the API hit a single URL, resources are not identified by a unique URIs.
Web Service Contracts
A web service contract specifies the operations and data types for an API. Contracts are important because they establish a well defined set of expectations between an API service and the clients that consume it. Contracts also help in versioning the API (see below). Cloud Servers and EC2 APIs both offer support for human readable contracts in the form of Developer Guides and machine readable contracts that can be used to validate operations and to generate code. To define operations, the Cloud Servers API uses WADL for its machine readable contract and EC2 uses WSDL for its SOAP based API. Operations are not defined in a machine readable manner in EC2’s Query API. All APIs, however, define their entities (servers, flavors, images,etc.) in terms of XML Schema (XSD).
Cloud Servers API contracts offer a greater level of detail in some important respects. For example, when defining operations the Cloud Servers API defines what things can go wrong on a per operation basis: There are six distinct failures that can occur when requesting details about a server and eight distinct failures that can occur when changing an administrative password. These possibilities are described both in the Cloud Servers Developer Guide and in the WADL. EC2, on the other hand, defines a set of Error Codes in their API reference manual, but does not associate these codes to individual operations. Additionally, although WSDL offers support for associating faults with operations, EC2’s WSDL contract does not do so. In EC2, it becomes the responsibility of the client to determine what error conditions are possible when performing one operation or another. This itself can be error prone – especially when one considers that error conditions may change from one revision of the API to the next.
Cloud Servers API contracts also offer greater refinement when defining data types. For example, both Cloud Servers and EC2 Instances can be in a certain state: the server is running, or it is building, it is suspended or it is in error. Both APIs define an XSD type to capture this state:
The big difference here is that the Cloud Servers type defines all possible values for the state and gives an explanation for what each means. In EC2, the state is defined as an integer and a string, it becomes the responsibility of the client to determine what the possible states are, and more importantly what it means for an instance to be in a certain state.
The Cloud Server’s API performs authentication via a simple token-based protocol. A token can be obtained via a REST call from a user’s credentials. The token is then passed in a header on every subsequent request. The HTTPS protocol is used to prevent the token from being stolen. Token’s are ephemeral and eventually expire. At any time, the system may ask that a token be renewed by re-prompting for credentials.
EC2’s authentication mechanism involves digitally signing every request. Each user is given an a key pair. Requests in both the Query and SOAP API must be strictly encoded and ordered – in the Query API, HTTP query parameters must be in alphabetical order and their content must be strictly URL encoded. For example,
Given the request:
https://ec2.amazonaws.com/?Action=DescribeImages &ImageId.1=ami-2bb65342 &Version=2009-11-30 &Expires=2008-02-10T12%3A00%3A00Z &SignatureVersion=2 &SignatureMethod=HmacSHA256 &AWSAccessKeyId=
A signature string must be created from the parameters. The string must contain parameters in alphabetical order with URL encoded values:
GET\n ec2.amazonaws.com\n /\n AWSAccessKeyId= &Action=DescribeImages &Expires=2008-02-10T12%3A00%3A00Z &ImageId.1=ami-2bb65342 &SignatureMethod=HmacSHA256 &SignatureVersion=2 &Version=2009-11-30
The string is signed and the Base 64 URL encoded signature is passed as a request parameter:
https://ec2.amazonaws.com/?Action=DescribeImages&ImageId.1=ami-2bb65342 &Version=2009-11-30 &Expires=2008-02-10T12%3A00%3A00Z &Signature=&SignatureVersion=2 &SignatureMethod=HmacSHA256 &AWSAccessKeyId=
Amazon’s authentication mechanism has the ability to securely validate requests without the need to use the HTTPS protocol. The mechanism, however, can be error prone and comes at the price of complicating client code.
Both Cloud Servers and EC2 services set limits on certain operations to prevent abuse. In Cloud Servers, however, these limits can be queried via the API. For example, by default, Cloud Servers allows an account to create no more than 50 servers per day – it is possible to determine this fact via the API. Additionally, should an account create 50 servers within a day, the exact time when an additional server may be created can be queried programatically.
The Cloud Servers API and the EC2 API are both asynchronous. This means that a request to perform an action does not wait until the action completes before returning. To test the status of operations, developers must asynchronously poll to determine the state of a particular image or server instance.
The Cloud Servers API provides a “changes-since” operation that can provide for efficient polling of groups servers or images with a single call. Changes-since works by providing developers with a list of changes that have occurred since a particular point in time. Additionally, Cloud Servers supports the standard HTTP If-Modified-Since header which allows for a conditional GET operation for efficient polling of a single entity.
Both Cloud Servers and EC2 APIs support calls for requesting collections of servers and images. The Cloud Servers API additionally offers support for paginated collections: When dealing with long lists of items a developer can request to receive a page of items of a certain size. This is useful when presenting lists of items in a user interface since it is possible to request a page at a specified offset – thus reducing the amount of memory that needs to be maintained on the client side.
Both Cloud Servers and EC2 APIs support versioning. In Cloud Servers, the base endpoint URL denotes the requested version:
In the EC2 Query API, the requested version is passed as a parameter:
https://ec2.amazonaws.com/?Action=DescribeImages&ImageId.1=ami-2bb65342 &Version=2009-11-30&Expires=2008-02-10T12%3A00%3A00Z &Signature=&SignatureVersion=2 &SignatureMethod=HmacSHA256 &AWSAccessKeyId=
In the EC2 SOAP API, the requested version is determined by the namespace of the request XML:
There are two features that sets the Cloud Servers API apart: First, information about the current version and all available versions of the API can be queried. Version information includes the current version status and pointers to the human readable and machine processable API contract for that version:
Another subtle feature is that the API service has a well documented lifecycle. The lifecycle consists of an ordered set of version states:
BETA → CURRENT → DEPRECATED
Having a query-able version allows developers to develop clients that can inform their users when a new version of the API is available.
We hope the information provided has helped you understand our API better, why you would want to use it and what makes it different than that of Amazon’s EC2 API. Of course, everyone has their own preference and needs, and that is why we built our API on open standards and have followed a RESTful practice. We have no intention to lock anybody in and believe that solid, well-received cloud standards are the key to avoiding cloud lock-in. We encourage your continuous feedback and appreciate your contributions.