After all my strategy for OCCI was to follow Google’s example with GData by adding some necessary functionality (a search interface, caching directives, resource-specific attributes, etc.). Most of the heavy lifting was actually being done by AtomPub, thus avoiding a huge amount of tedious and error-prone protocol writing (around 20,000 words of it) – something which OGF and the OCCI working group isn’t really geared up for anyway. This is clearly a workable and well-proven approach as it as been adopted strategically by both Microsoft and Google and also tactically by Salesforce and IBM, among others. Best of all adding things like queries and versioning is a manageable workload while starting from scratch is most certainly not.
But what if there were an easier way? Recall that the problem we are trying to solve is exposing a flexible interface to an arbitrarily large collection of interconnected compute, storage and network resources. We need to be able to describe and manipulate the resources (CRUD), associate them with each other via rich links (e.g. links with attributes like local identifiers – eth0, sda, etc.) and change their state (start, stop, restart, etc.), among other things.
Representational State Transfer (REST)
Actually we’re not talking about exposing the resources themselves (that would be impossible) but various representations of those resources – like Plato’s shadows on the cave walls – this is the “REpresentational” in “REpresentational State Transfer (REST)”. There’s an infinite number of possible representations so it’s impossible to try to capture them all now, but here’s some examples:
- An Open Virtualisation Format (OVF) serialisation of a compute resource
- A platform-specific descriptor file (e.g. VMX)
- A complete archive of the virtual machine with its dependencies (OVA)
- A graphical image of the console at a given point in time (‘snapshot’)
- A video stream of the console for archiving/audit purposes (ala Citrix’s Project Iris)
- The console itself (e.g. SSH, ICA, RDP, VNC)
- Build documentation (e.g. PDF, ODF)
- Esoteric enterprise requirements (e.g. NMS configuration)
It doesn’t take a rocket scientist to spot the correlation between this and HTTP’s existing content negotiation functionality (whereby a client can ask for a specific representation of a given resource – e.g. HTML vs PDF) so this is already pretty much solved for us (see HTTP’s Accept: header for the details). For bonus points this information should be exposed in the URI as it’s not always possible or convenient to set headers ala:
- http://example.com/.atom (using filename extensions)
- http://example.com/;content-type=text/html (using the full Internet media type)
But what about the links? As I explained yesterday the web is built on links embedded in HTML documents using the A tag. Atom also provides enhanced linking functionality via the LINK element, where it is also possible to specify content types, languages, etc. In this case however we want to allow resources to be arbitrary types and more often than not we won’t have the ability to link within the payload itself. This leaves us with two options: put the links in the payload anyway by relying on a meta-model like Atom (or one we roll ourselves) or find some way to represent them within HTTP itself.
Enter HTTP headers which are also extensible and, as it turns out, in the process of being extended (or at least refined) to handle this very requirement by fellow down under, Mark Nottingham. See the “Web Linking” IETF Internet-Draft (draft-nottingham-http-link-header, at the time of writing version 05) for the nitty gritty details and the ietf-http-wg list for some current discussions. Basically it clarifies the existing Link: headers and the result looks something like this:
Link: <http://example.com/TheBook/chapter2>; rel="previous"; title="previous chapter">
The Link: header itself is also extensible so we can faithfully represent our model by adding e.g. the local device name when linking storage and network resources to compute resources and other requisite attributes. It would be helpful if the content-type were also specified (Atom allows for multiple links of the same relation provided the content-type differs for example) but language is already covered by HTTP (it doesn’t seem useful to advertise French links to someone who already asked to speak English).
It’s also interesting to note that earlier versions of the HTTP RFCs actually [poorly] specified both the Link: headers as well as LINK and UNLINK methods for maintaining links between web resources. John Pritchard had a crack at clarification in the Efficient HyperLink Maintenance for HTTP I-D but like most I-Ds this one seems to have died after 6 months, and with it the methods themselves. It seems to me that adding HTTP methods at this time is a drastic (and almost certainly infeasible) action, especially for something that could just as easily be accomplished via headers ala Set-Cookie: (too bad the I-D doesn’t specify how to add/delete/modify links!). In the simplest sense a Link: header appearing in a PUT or POST could replace the existing one(s) but something more elegant for acting on individual links would be nice – probably a discussion worth having on the ietf-http-wg list.
Organisation of Information
Looking back to Atom for a second we’re still missing some key functionality:
- Atom id -> HTTP URL
- Atom updated -> HTTP Last-Modified: Header
- Atom title and summary -> Atom/HTTP Slug: Header or equivalent
- Atom link -> HTTP Link: Header
- Atom category -> ???
Houston, we have a problem. OCCI use cases range from embedded hypervisors exposing a single resource to a single entry-point for an entire enterprise or the “Great Global Grid” – we need a way to organise, categories and search for the information, likely including:
- Free text search via a Google-style “?q=firewall” syntax
- Taxonomy via categories (already done for Atom) for things like “Operating System” and “Data Center”
- Folksonomy via [user] tags (already done for Atom and bearing in mind that tag spaces are cool) for things like “testlab”
Fortunately the good work already done in this area for Atom would be realatively easy to port to a Category: HTTP header, following the Link: header example above. In the mean time a standard search interface (including category support) is trivial and thanks to Google, already done.
Structured Data Formats
HTML also resolves another pressing issue – what format to use for submitting key-value pairs (which constitutes a large part of what we need to do with OCCI). It gives us two options:
- application/x-www-form-encoded which is simple but quickly gets messy with encoding and non-ASCII characters
- multipart/form-data which is less efficient but will handle pretty much whatever you throw at it (including large files)
The advantages of being able to create a resource from a web form simply by POSTing to the collection of resources (e.g. http://example.com/compute), and with HTML 5 by PUTting the resource in place directly (e.g. http://example.com/compute/<uuid>) are immediately obvious. Not only does this help make the human and programmable web one and the same (which in turn makes it much easier for developers/users to kick the tyres and understand the API) but it means that scripting even advanced tasks with curl/wget would be trivial. Plus there’s no place for time-wasting religious arguments about angle brackets (XML) over curly braces (JSON).
RESTful State Machines
Something else which has not sat well with me until I spent the weekend ingesting RESTful Web Services book (by Leonard Richardson and Sam Ruby) was the “actuator” concept we picked up from the Sun Cloud APIs. This breaks away from RESTful principles by exposing an RPC-style API for triggering state changes (e.g. start, stop, restart). Granted it’s an improvement on the alternative (GETting a resource and PUTting it back with an updated state) as Tim Bray explains in RESTful Casuistry (to which Roy Fielding and Bill de hÓra also responded), but it still “feels funky”. Sure it doesn’t make any sense to try to “force” a monitored status to some other value (for example setting a “state” attribute to “running”), especially when we can’t be sure that’s the state we’ll get to (maybe there will be an error or the transition will be dependent on some outcome over which we have no control). Similarly it doesn’t make much sense to treat states as nouns, for example adding a “running” state to a collection of states (even if a resource can be “running” and “backing up” concurrently). But is using URLs as “buttons” representing verbs/transitions the best answer?
What makes more sense [to me] is to request a transition and check back for updates (e.g. by polling or HTTP server push). If it’s RESTful to POST comments to an article (which in addition to its own contents acts as a collection of zero or more comments) then POSTing a request to change state to a [sub]resource also makes sense. As a bonus these can be parametrised (for example a “resize” request can be accompanied with a “size” parameter and a “stop” request sent with clarification as to whether an “ACPI Off” or “Pull Cord” is required). Transitions that take a while, like “format” on a storage resource, can simply return HTTP 201 Accepted so we’ve got support for asynchronous actions as well – indeed some requests (e.g. “backup”) may not even be started immediately. We may also want to consider using something like Post Once Exactly (POE) to ensure that requests like “restart” aren’t executed repeatedly and that we can cancel requests that the system hasn’t had a chance to deal with yet.
Exactly how this should look in terms of URL layout I’m not sure (perhaps http://example.com/<resource>/requests) but being able to enumerate the possible actions as well as acceptable parameters (e.g. an enum for variations on “stop” or a range for “resize”) would be particularly useful for clients.
This is all well and good for individual resources, but collections are still a serious problem. There are many use cases which involve retrieving an arbitrarily large number of resources and making a HTTP request for each (as well as requests for enumeration etc.) doesn’t make sense. More importantly, it doesn’t scale – particularly in enterprise environments where requests via proxies and filters can suffer from high latency (if not low bandwidth).
One potential solution is to strap multiple HTTP message entities together as a multipart document, but that’s hardly clean and results in some hairy coding on the client side (e.g. manual manipulation of HTTP messages that would otherwise be fully automated). The best solution we currently have for this problem (as evidenced by widespread deployment) is AtomPub so I’m still fairly sure it’s going to have to make an appearance somewhere, even if it doesn’t wrap all of the resources by default.