[Ovirt-devel] OVirt public API

David Lutterkort dlutter at redhat.com
Tue Jul 15 23:11:31 UTC 2008


Here is my current thinking around a public API for OVirt. The basic
idea is that that API will expose all operations that are available
through the WUI, with small adaptations to the fact that it's an API,
and not an interactive interface.

In particular, the API will (eventually) support the following:

  * Lifecycle control for virtual machines
    (start/stop/suspend/resume/migrate)

  * Management of the various pools, i.e. host, storage and VM pools

  * Querying of information about the above; I'd explicitly exclude
    performance data from this 'information' - I think that should be
    communicated by different means (e.g., collectd)

Architecturally, the API will be a remote API over HTTP, using a RESTful
style; in a nutshell, that means that clients make calls through HTTP
requests, with arguments and results suitably encoded - for GET
requests, that simply means ordinary request params, for POST, it's TBD
which possible ways to serialize data is preferrable. Obvious candidates
are XML, YAML, and JSON; right now, I am leaning towards
XML. Stylistically, REST uses URL's to represent objects (or 'nouns')
and different HTTP methods to retrieve and/or change those objects
('verbs') You can think of the HTTP methods GET, POST, PUT, DELETE as
analogous to the SQL actions select, insert, update, and delete,
respectively. Or the show/create/update/delete methods in Rails
controllers.

Besides being lightweight, a RESTful API is also very attractive because
of the support for it in Rails 2 (ActionController::Resources on the
server side, and ActiveResource for clients) That support takes away a
lot of the headaches around serialization of objects, routing etc.

Objects
=======

Each object (VM, host, storage pool etc.) needs to be identified by a
unique URL. For a VM, this may be /vms/7. Since the internal id '7'
appears in the URL, we need a way to find VM's by various criteria, for
example doing a 'GET /vms?uuid=...' will return the URL to a VM with
that UUID, or 'GET /vms?num_vcpus_allocated=2' lists all VM's that have
2 vcpus. More interestingly, something like 'GET /storage_volumes/5/vms'
would list all the VM's that use storage volume 5.

Toplevel objects accessible in this way are VM's, hosts, and the various
pools. Besides retrieving a readonly representation of them, changes can
be made, for example by doing a 'POST /vms' with a suitable body to
create a new VM.

One difficulty is the inherently asynchronous nature of OVirt, where you
ask for a state change (e.g. start a VM) but that doesn't happen until
some time later. It's probably best to expose those pending state
changes nested underneath the object to which they apply,
e.g. /vms/7/tasks would give you a list of the tasks queued for VM 7,
and doing a 'POST /vms/7/tasks' can be used to queue a new task for VM
7. One thing that's not entirely clear is whether and how the actual
tasks that wind up in task-o-matic map to the tasks in the public
API. For the currently supported tasks, there's no need to beat around
the bush, and they correspond directly to actions one would want to
perform through the API. That might not be true in the future when we
get more complex operations like 'clear_host' that may be decomposed
into multiple tasks in task-o-matic. We definitely don't want to leak
too much implementation detail through the public API.

Architecture
============

For now, the API should just run side-by-side with the WUI, in the same
web server, simply because much of the underlying infrastructure, from
models to authentication is shared between the two. If we ever need an
API-only or WUI-only server, it's probably easiest to just configure
that out.

Rails' ActiveResource package provides a convenient way for users to
access this API in Ruby - I am not entirely clear on how people who
insist on writing Python will access the API. At worst, somebody would
have to either write code that deserializes Rails' XML representation of
objects into Python objects; though from a quick googling it seems that
there are a couple of fledgling projects to bridge the ActiveResource
<-> Python gap. A second option is to provide output from API methods
through another format, like JSON, which might be better supported for
Python deserialization.

Another small wrinkle is that we want to keep the URL's for API
resources separate from URL's used by the WUI. The whole API should
probably live underneath a /api or /rest prefix on the server, though
common logic between WUI and API methods would be factored into
controllers and/or helpers used by both. There are some examples on the
web where WUI and API are served by the same controller, and only the
views change between the two, but I am not sure if that is really
realistic for a decent sized app.

Implementation
==============

To get started, I'll hack out some of the simpler API calls, like
updating the data for a VM.

David





More information about the ovirt-devel mailing list