|
From: | Anthony Liguori |
Subject: | Re: [Qemu-devel] [RFC/RFA PATCH] qapi: detect extra members inside structs |
Date: | Mon, 19 Mar 2012 19:49:46 -0500 |
User-agent: | Mozilla/5.0 (X11; Linux x86_64; rv:10.0.2) Gecko/20120216 Thunderbird/10.0.2 |
On 03/19/2012 06:45 PM, Michael Roth wrote:
So IMO, returning arguments actually seems easier for both clients and the server, and is more resilient to downstream changes. It does require a more formal specification of the protocol though. Basically: "an option/field may not be supported in older/future versions of QEMU, so it is up to the client to check in advance by referencing the QAPI schema for their qemu version or programatically via get_schema(<command>)"The complexity of writing a client using get_schema() is close to staggering :-/I'm not sure, I mean, take libvirt, you need to marshall up the arguments anyway and put them into a QMP payload, so in that case the client developer is aware of the schema that they're coding against, and also understand the QAPI schema specification, and if the schema is nested then so is the client version of that "schema". So, conceptually at least, it seems like it wouldn't be that big a jump to maintain an internal representation of their schema to programatically check against the specification they were coding against, it's just the part where they then need to bake it into the client implementation that's a bit heavy-handed.
So let's work through a few examples. Today, you have to maintain a list of commands returned from query-commands and check for set membership:
if 'query-netdev2' in commands: qmp.query_netdev2(foo) else: qmp.query_netdev()Pretty simple. If we have a schema representation, we'll need to be able to check for arguments. That means we need a way to check if a command has an argument. We could do this as nested lists:
if (commands.has_key('query-netdev') and commands['query-netdev']['args'].has_key('interface')): qmp.query_netdev(foo) else: qmp.query_netdev()This is only really possible in a dynamically typed language, which sucks, but let's ignore that for now. This is a bit more complicated but unfortunately, it's not enough.
Because we can add members to structures and structures can be arguments. So we really need a way to say:
1) Do we have the query-netdev command 2) Does it take a parameter called interface of type NetDevArgument 3) Does the NetDevArgument have a member called 'foo'.But this actually can be arbitrarily deep in terms of complex. Maybe you make a simple query language so you can execute schema queries in a single line.
So you have an interface definition that is the schema that describes an unstructured wire protocol and a query language to determine when and how the schema changes. If that doesn't ring a bell to you, congratulations, you've invented SOAP.
The interface description in SOAP is WSDL and XPath is the query language. Writing a SOAP client is a train wreck. It's so bad that even in dynamic languages, people almost always use code generators.
A good RPC makes the client simple. If that means we need to take care when introducing new interfaces, then it's a small price to pay for avoiding the nightmares of an over engineered RPC like SOAP.
Regards, Anthony Liguori
Thinking about it more the, this does seem to be completely at odds with any future prospects of a libqmp, so that's a pretty big trade-off...Regards, Anthony Liguori
[Prev in Thread] | Current Thread | [Next in Thread] |