xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Anthony PERARD <anthony.perard@citrix.com>
To: Ian Jackson <ian.jackson@citrix.com>
Cc: xen-devel@lists.xenproject.org, Wei Liu <wei.liu2@citrix.com>
Subject: Re: [PATCH v3.1] libxl: Design of an async API to issue QMP commands to QEMU
Date: Wed, 4 Jul 2018 12:11:27 +0100	[thread overview]
Message-ID: <20180704111127.GA2195@perard.uk.xensource.com> (raw)
In-Reply-To: <23355.36022.532092.791702@mariner.uk.xensource.com>

On Tue, Jul 03, 2018 at 03:48:22PM +0100, Ian Jackson wrote:
> Anthony PERARD writes ("[PATCH v3.1] libxl: Design of an async API to issue QMP commands to QEMU"):
> > All the functions will be implemented in later patches.
> 
> Thanks, this really makes things clearer for me.
> 
> > What do you think of this design? This is the same as in my patch series
> > with new names (to avoid confusion with libxl___ev_*) and documentation.
> > 
> > I'll write something as well for the internal of the engine (the QMP
> > client itself).

Before replying to this email, here is the description of what state a
QMP connection can be. This states are only internal to libxl_qmp.c, the
rest of libxl doesn't need to know.

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1235,6 +1235,97 @@
     return ret;
 }
 
+/* ------------ Implementation of asynchronous QMP calls ------------ */
+
+/*
+ * This are different state possible when the QMP client (libxl) is waiting.
+ * Transition from one state to the other is listed after.
+ *
+ * States:
+ *   Undefined
+ *   Disconnected
+ *      nothing, no allocated ressources
+ *   Connecting
+ *      Have allocated ressources,
+ *      Have connected to the QMP socket,
+ *      Waiting for server greeting.
+ *   Capability Negociation
+ *      QMP server is in Capabilities Negotiation mode.
+ *      Waiting for a response to the "qmp_capabilities" command
+ *   Connected
+ *      QMP server is in command mode,
+ *      commands can be issued
+ *
+ * Here is the transition from one state to the next:
+ *  Disconnected -> Connecting:
+ *    Connect to the QMP socket.
+ *  Connecting -> Capability Negociation
+ *    Server greeting received
+ *    Send "qmp_capabilities"
+ *  Capability Negociation -> Connected
+ *    Response to "qmp_capabilities" received"
+ *
+ * checkout qemu.git:docs/interop/qmp-spec.txt for more information.
+ */


> > +/*
> > + * This struct is used to register one command to send to QEMU with an
> > + * associated callback.
> 
> You still use the word `register' which I don't think is right.  It
> makes it sound as if there is a separate `registration' and `sending'.
> 
> How about
> 
>    This facility allows a command to be sent to qemu, and the response
>    to be handed to a callback function.  Each libxl__qmp_cmd_state
>    handles zero or one outstanding command; if multiple commands are
>    to be sent concurrently, multiple libxl__qmp_cmd_state's must be
>    used.
> 
> or some such ?

That's looks better.

> > + * Possible states:
> > + *  Undefined
> > + *    Might contain anything.
> > + *  Idle
> > + *    Struct contents are defined enough to pass to any
> > + *    libxl__qmp_cmd_* functions but is not registered and callback
> > + *    will not be called. The struct does not contain references to
> > + *    any allocated resources so can be thrown away.
> > + *  Active
> > + *    Currently waiting for a response from QEMU, and callback can be
> > + *    called. _dispose must be called to reclaim resources.
> 
> I don't think this set of states is accurate.  In particular, your API
> description (about connection management) implies that there are at
> least these states:
>   (i) undefined
>   (ii) there is no qmp connection open
>   (iii) we have sent a command and are expecting a callback
>   (iv) there is a qmp connection open, but no command is outstanding
> 
> (iv) does not fit into any of the categories above.

I don't think the state of a qmp connection can fit into
libxl__qmp_cmd_state. The "Active" state doesn't mean that a qmp
connection is open or that the command have been sent. It merely mean
that the syscall socket(3) and connect(3) have return successfully, and
there will be an attempt later to sent the command to qemu.

> > +/*
> > + * Initialize libxl__qmp_cmd_state.
> > + *    Which must be in Undefined or Idle state.
> > + *    On return it is Idle.
> 
> You might want to abbreviate this state notation, eg as is done for
> libxl__xs_transaction_... .  So here you could just write
>        Undefined/Idle -> Idle

Will do.

> > +/*
> > + * Register a command to be issued to QEMU.
> 
> Again, "register" has been inherited from libxl_ev_*.  I think it
> would be clearer to say that this function
> 
>      Sends a command to QEMU.

The API I'm describing haven't send anything to QEMU yet, the command is
merely put in a queue, and an attempt to send it will be done later,
when QEMU is ready to receive commands and when the socket is not
blocked.

> Looking through libxl_internal.h again, I see that there is
> libxl__ev_child, which provides another model for handling a thing
> which is sort of, but not exactly, like a libxl__ev_FOO.  There, the
> struct is called libxl_ev_*, but the actual function names are quite
> different.  There is no libxl__ev_child_register, only
> libxl__ev_child_fork.  And libxl__ev_child_deregister is entirely
> absent.
> 
> So you could call your think libxl__ev_qmp but have functions
> libxl__ev_qmp_send and libxl__ev_qmp_dispose/destroy.
> (and _init of course).
> 
> If you do this you need to do like libxl__ev_child_fork does, and
> write commentary describing the ways in which a libxl__ev_qmp is not
> like most libxl__ev_FOO.
> 
> I think I mind less what the struct is called than what the functions
> are called.  Your send function should probably be _send or _exec.
> The dispose function can be _dispose or _destroy, or similar.

I look into that.

> > +struct libxl__qmp_cmd_state {
> > +    /* read-only once Active and from within the callback */
> > +    uint32_t domid;
> > +    libxl__qmp_cmd_callback *callback;
> 
> You copied this pattern from libxl__ev_FOO.  I don't object to it.
> 
> But in general, I have sometimes found it more convenient to put these
> parameters in the struct and expect callers to fill them in.  You are
> doing that with the carefd.  Maybe you want to do it with all of
> them ?  See libxl__datacopier_start for an example.
> 
> Up to you.  I don't object to mixing the two styles within the same
> facility provided the internal docs are clear.

I've done the carefd differently because I didn't know how to put it
into the function parameters, beside having a new function. But your
sugestion about having the caller fill the struct sound good. I'll do
that. That way, a caller will know in which states are the different
fields.

> > +    /* private */
> 
> You should say "private for libxl__qmp_cmd_...".

Will do.

> > +    /*
> > +     * This value can be initialise before calling _qmp_cmd_exec. The
> > +     * file descriptor will sent to QEMU along with the command, then
> > +     * the fd will be closed.
> > +     */
> > +    libxl__carefd *efd;
> 
> Why not
>        libxl__carefd efd;
> ?

The libxl__carefd_* API returns a newly allocated efd, a pointer. I
can't preallocate it.

> Also, I don't think this description of the semantics is right.  The
> caller must always somehow arrange to initialise this value.
> Presumably _init clears it ?  Certainly this as a parameter to the
> operation, this should be up with domid and callback.
> 
> Maybe you want comments like the ones in libxl__datacopier_state etc.,
> which say /* caller must fill these in */.
> 
> And, you probably want to make it clear that the fd remains open in
> the libxl process.  (I assume it does.)

Well I was closing the fd once it was sent to QEMU. But we can have the
callbacks takes care of closing it instead.

> > +libxl__qmp_error_class = Enumeration("qmp_error_class", [
> > +    # No error
> > +    (0, "NONE"),
> > +    # Error generated by libxl (e.g. socket closed unexpectedly, no mem, ...)
> > +    (1, "libxl_error"),
> > +    # QMP error classes described in QEMU sources code (QapiErrorClass)
> > +    (2, "GenericError"),
> > +    (3, "CommandNotFound"),
> > +    (4, "DeviceNotActive"),
> > +    (5, "DeviceNotFound"),
> > +    # Unrecognized QMP error class
> > +    (6, "Unknown"),
> 
> Are these numbers from qmp ?  Why not assign a bunch of libxl error
> values instead ?

No, these are strings from QEMU, numbers doesn't matter. Also I don't
know how well those are going to fit into libxl errors.

FYI, here is the description of the different errors generated by QEMU:

(qemu.git:qapi/common.json)
# @QapiErrorClass:
#
# QEMU error classes
#
# @GenericError: this is used for errors that don't require a specific error
#                class. This should be the default case for most errors
#
# @CommandNotFound: the requested command has not been found
#
# @DeviceNotActive: a device has failed to be become active
#
# @DeviceNotFound: the requested device has not been found

QEMU always associate an error messages when it send an error, so the
only thing t odo with GenericError is to log that message.

> I hope this review is helpful.
> 
> Thanks,
> Ian.

-- 
Anthony PERARD

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  reply	other threads:[~2018-07-04 11:11 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-01 14:36 [PATCH v3 00/31] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
2018-06-01 14:36 ` [PATCH v3 01/31] libxl_event: Fix DEBUG prints Anthony PERARD
2018-06-27 14:19   ` Ian Jackson
2018-06-01 14:36 ` [PATCH v3 02/31] libxl_qmp: Documentation of the logic of the QMP client Anthony PERARD
2018-06-27 14:20   ` Ian Jackson
2018-06-01 14:36 ` [PATCH v3 03/31] libxl_qmp: Fix use of DEBUG_RECEIVED Anthony PERARD
2018-06-27 14:20   ` Ian Jackson
2018-06-01 14:36 ` [PATCH v3 04/31] libxl_json: fix build with DEBUG_ANSWER Anthony PERARD
2018-06-27 14:22   ` Ian Jackson
2018-07-17 14:35     ` Anthony PERARD
2018-06-01 14:36 ` [PATCH v3 05/31] libxl_qmp: Move the buffer realloc to the same scope level as read Anthony PERARD
2018-06-27 14:25   ` Ian Jackson
2018-06-01 14:36 ` [PATCH v3 06/31] libxl_qmp: Add a warning to not trust QEMU Anthony PERARD
2018-06-27 14:25   ` Ian Jackson
2018-06-01 14:36 ` [PATCH v3 07/31] libxl_qmp: Learned to send FD through QMP to QEMU Anthony PERARD
2018-06-27 14:26   ` Ian Jackson
2018-06-27 16:50     ` Anthony PERARD
2018-06-28  9:56       ` Ian Jackson
2018-06-01 14:36 ` [PATCH v3 08/31] libxl_qmp: Have QEMU save its state to a file descriptor Anthony PERARD
2018-06-27 14:29   ` Ian Jackson
2018-06-01 14:36 ` [PATCH v3 09/31] libxl_qmp: Move struct sockaddr_un variable to qmp_open() Anthony PERARD
2018-06-27 14:31   ` Ian Jackson
2018-06-27 16:54     ` Anthony PERARD
2018-06-01 14:36 ` [PATCH v3 10/31] libxl_qmp: Move buffers to the stack of qmp_next Anthony PERARD
2018-06-27 14:32   ` Ian Jackson
2018-06-27 16:58     ` Anthony PERARD
2018-06-28  9:57       ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 11/31] libxl_qmp: Remove unused yajl_ctx form handler Anthony PERARD
2018-06-27 14:32   ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 12/31] libxl_json: constify libxl__json_object_to_yajl_gen arguments Anthony PERARD
2018-06-27 14:32   ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 13/31] libxl_qmp: Separate QMP message generation from qmp_send_prepare Anthony PERARD
2018-06-27 14:45   ` Ian Jackson
2018-06-27 17:12     ` Anthony PERARD
2018-06-01 14:37 ` [PATCH v3 14/31] libxl_qmp_ev: Introduce libxl__ev_qmp_start() to connect to QMP Anthony PERARD
2018-06-27 15:07   ` Ian Jackson
2018-06-28 11:28     ` Anthony PERARD
2018-06-28 11:44       ` Ian Jackson
2018-06-28 13:01         ` Anthony PERARD
2018-06-01 14:37 ` [PATCH v3 15/31] libxl_qmp_ev: Implement fd callback and read data Anthony PERARD
2018-06-27 15:10   ` Ian Jackson
2018-06-28 11:33     ` Anthony PERARD
2018-06-28 11:37       ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 16/31] libxl_json: Allow partial parsing Anthony PERARD
2018-06-01 14:37 ` [PATCH v3 17/31] libxl_json: Enable yajl_allow_trailing_garbage Anthony PERARD
2018-06-01 14:37 ` [PATCH v3 18/31] libxl_json: libxl__json_object_to_json Anthony PERARD
2018-06-27 15:51   ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 19/31] libxl_qmp_ev: Parse JSON input from QMP Anthony PERARD
2018-06-01 14:37 ` [PATCH v3 20/31] libxl_qmp: Introduce libxl__ev_qmp functions Anthony PERARD
2018-06-01 14:37 ` [PATCH v3 21/31] libxl_qmp_ev: Handle write to socket Anthony PERARD
2018-06-01 14:37 ` [PATCH v3 22/31] libxl_qmp: Simplify qmp_response_type() prototype Anthony PERARD
2018-06-27 16:03   ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 23/31] libxl_qmp_ev: Handle messages from QEMU Anthony PERARD
2018-06-01 14:37 ` [PATCH v3 24/31] libxl_qmp_ev: Respond to QMP greeting Anthony PERARD
2018-06-27 16:07   ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 25/31] libxl_qmp_ev: Disconnect QMP when no more events Anthony PERARD
2018-06-01 14:37 ` [PATCH v3 26/31] libxl_qmp: Disable beautify for QMP generated cmd Anthony PERARD
2018-06-27 16:07   ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 27/31] libxl_qmp: Implement libxl__qmp_insert_cdrom_ev Anthony PERARD
2018-06-27 16:10   ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 28/31] libxl_disk: Cut libxl_cdrom_insert into step Anthony PERARD
2018-06-01 14:37 ` [PATCH v3 29/31] libxl_disk: Have libxl_cdrom_insert use libxl__ev_qmp Anthony PERARD
2018-06-27 16:12   ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 30/31] libxl_dm: Pre-open QMP socket for QEMU Anthony PERARD
2018-06-27 16:14   ` Ian Jackson
2018-06-01 14:37 ` [PATCH v3 31/31] libxl: QEMU startup sync based on QMP Anthony PERARD
2018-06-27 16:16   ` Ian Jackson
2018-07-26 14:59     ` Anthony PERARD
2018-06-01 14:47 ` [PATCH v3 00/31] libxl: Enable save/restore/migration of a restricted QEMU + libxl__ev_qmp_* Anthony PERARD
2018-07-03  9:47 ` [PATCH v3.1] libxl: Design of an async API to issue QMP commands to QEMU Anthony PERARD
2018-07-03 14:48   ` Ian Jackson
2018-07-04 11:11     ` Anthony PERARD [this message]
2018-07-12 16:36       ` Ian Jackson
2018-07-16 15:27         ` Anthony PERARD
2018-07-16 15:28           ` [PATCH v3.2] " Anthony PERARD
2018-07-16 16:33             ` Anthony PERARD
2018-07-16 17:04               ` [PATCH v3.2] libxl: Design of an async API to issue QMP commands to QEMU [and 1 more messages] Ian Jackson
2018-07-18 10:30                 ` Anthony PERARD

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180704111127.GA2195@perard.uk.xensource.com \
    --to=anthony.perard@citrix.com \
    --cc=ian.jackson@citrix.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).