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
On Tue, Jul 15, 2008 at 04:11:31PM -0700, David Lutterkort wrote:> 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.I like the REST concept, especially the fact that it will leverage the model code we already have in oVirt. However, I would very much like to have a command line interface (oVirsh?) to go along with the API. Does that seem doable on top of a REST API? XML-RPC I assume is covered if we use XML to serialize data.> 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.This is great, looking forward to seeing what you come up with. I do think we will need to have some form of python "bindings" -- surely python has some concept of REST? Take care, --Hugh
David Lutterkort wrote:> 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. >I would make an argument for XMLRPC/SSL based on that a lot of our management applications already have XMLRPC API's (such as Spacewalk/Cobbler/etc), and that serialization and more remote faults are supported. Having an app have to speak to multiple API types if of course going to be a reality. That being said, REST is definitely workable, and as long as there is an API, I think most people will be reasonably happy. Basically with XMLRPC you don't have to write any wrapper code around the API caller and it just works as if it were a local API, which is nice> 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 > > > _______________________________________________ > Ovirt-devel mailing list > Ovirt-devel at redhat.com > https://www.redhat.com/mailman/listinfo/ovirt-devel >