qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@redhat.com>
To: "Daniel P. Berrangé" <berrange@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>,
	"Richard W.M. Jones" <rjones@redhat.com>,
	qemu-block@nongnu.org, qemu-devel@nongnu.org
Subject: Re: [PATCH] docs: show how to spawn qemu-storage-daemon with fd passing
Date: Mon, 1 Mar 2021 16:50:14 +0000	[thread overview]
Message-ID: <YD0bRoy34wH8slYj@stefanha-x1.localdomain> (raw)
In-Reply-To: <YD0L6r68S+Rv8a+R@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 4741 bytes --]

On Mon, Mar 01, 2021 at 03:44:42PM +0000, Daniel P. Berrangé wrote:
> On Mon, Mar 01, 2021 at 03:39:06PM +0000, Richard W.M. Jones wrote:
> > On Mon, Mar 01, 2021 at 03:31:59PM +0000, Stefan Hajnoczi wrote:
> > > The QMP monitor, NBD server, and vhost-user-blk export all support file
> > > descriptor passing. This is a useful technique because it allows the
> > > parent process to spawn and wait for qemu-storage-daemon without busy
> > > waiting, which may delay startup due to arbitrary sleep() calls.
> > > 
> > > This Python example is inspired by the test case written for libnbd by
> > > Richard W.M. Jones <rjones@redhat.com>:
> > > https://gitlab.com/nbdkit/libnbd/-/commit/89113f484effb0e6c322314ba75c1cbe07a04543
> > > 
> > > Thanks to Daniel P. Berrangé <berrange@redhat.com> for suggestions on
> > > how to get this working. Now let's document it!
> > > 
> > > Reported-by: Richard W.M. Jones <rjones@redhat.com>
> > > Cc: Kevin Wolf <kwolf@redhat.com>
> > > Cc: Daniel P. Berrangé <berrange@redhat.com>
> > > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > > ---
> > >  docs/tools/qemu-storage-daemon.rst | 38 ++++++++++++++++++++++++++++--
> > >  1 file changed, 36 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/docs/tools/qemu-storage-daemon.rst b/docs/tools/qemu-storage-daemon.rst
> > > index f63627eaf6..45854c131e 100644
> > > --- a/docs/tools/qemu-storage-daemon.rst
> > > +++ b/docs/tools/qemu-storage-daemon.rst
> > > @@ -101,10 +101,12 @@ Standard options:
> > >  
> > >  .. option:: --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>[,tls-creds=<id>][,tls-authz=<id>][,max-connections=<n>]
> > >    --nbd-server addr.type=unix,addr.path=<path>[,tls-creds=<id>][,tls-authz=<id>][,max-connections=<n>]
> > > +  --nbd-server addr.type=fd,addr.str=<fd>[,tls-creds=<id>][,tls-authz=<id>][,max-connections=<n>]
> > >  
> > >    is a server for NBD exports. Both TCP and UNIX domain sockets are supported.
> > > -  TLS encryption can be configured using ``--object`` tls-creds-* and authz-*
> > > -  secrets (see below).
> > > +  A listen socket can be provided via file descriptor passing (see Examples
> > > +  below). TLS encryption can be configured using ``--object`` tls-creds-* and
> > > +  authz-* secrets (see below).
> > >  
> > >    To configure an NBD server on UNIX domain socket path ``/tmp/nbd.sock``::
> > >  
> > > @@ -127,6 +129,38 @@ QMP commands::
> > >        --chardev socket,path=qmp.sock,server,nowait,id=char1 \
> > >        --monitor chardev=char1
> > >  
> > > +Launch the daemon from Python with a QMP monitor socket using file descriptor
> > > +passing so there is no need to busy wait for the QMP monitor to become
> > > +available::
> > > +
> > > +  #!/usr/bin/env python3
> > > +  import os
> > > +  import subprocess
> > > +  import socket
> > > +
> > > +  sock_path = '/tmp/qmp-{}.sock'.format(os.getpid())
> > 
> > Not sure how much you worry about the insecure / easily guessable tmp
> > path here.  I notice that there's already one in the surrounding
> > documentation (/tmp/nbd.sock) so maybe it's not a problem :-)
> > 
> > > +  with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as listen_sock:
> > > +      listen_sock.bind(sock_path)
> > > +      listen_sock.listen()
> > > +
> > > +      fd = listen_sock.fileno()
> > > +
> > > +      subprocess.Popen(
> > > +          ['qemu-storage-daemon',
> > > +           '--chardev', f'socket,fd={fd},server=on,id=char1',
> > > +           '--monitor', 'chardev=char1'],
> > > +          pass_fds=[fd],
> > > +      )
> > > +
> > > +  qmp_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
> > > +  qmp_sock.connect(sock_path)
> > 
> > A note that the order of opening the sockets is slightly different
> > from how I did it in the interop test.  But I believe it makes no
> > difference, as long as you don't connect to the socket until it's in
> > the listening state, which is what you're doing here.  So it should be
> > fine.
> 
> Nothing here is closing listen_sock in the parent though.
> 
> The trick of passing the listener FD into the child relies on the
> listener being closed in the parent, so that the parent can get
> a socket error if the child exits abnormally during startup. Keeping
> the listen socket open means the parent will wait forever for an
> accept() that never comes.

The listen socket is closed by the context manager at the end of the
'with' statement. This is the modern Python approach for resource
acquisition that also handles exceptions automatically. It's like RAII
in C++.

https://www.python.org/dev/peps/pep-0343/#specification-the-with-statement

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

  reply	other threads:[~2021-03-01 16:52 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-01 15:31 [PATCH] docs: show how to spawn qemu-storage-daemon with fd passing Stefan Hajnoczi
2021-03-01 15:39 ` Richard W.M. Jones
2021-03-01 15:44   ` Daniel P. Berrangé
2021-03-01 16:50     ` Stefan Hajnoczi [this message]
2021-03-01 16:56       ` Daniel P. Berrangé
2021-03-01 17:19         ` Stefan Hajnoczi
2021-03-01 16:53   ` Stefan Hajnoczi
2021-03-01 15:41 ` Daniel P. Berrangé
2021-03-01 15:49   ` Eric Blake
2021-03-01 16:06     ` Daniel P. Berrangé
2021-03-01 16:55       ` Stefan Hajnoczi
2021-03-02  4:47       ` Markus Armbruster

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=YD0bRoy34wH8slYj@stefanha-x1.localdomain \
    --to=stefanha@redhat.com \
    --cc=berrange@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=rjones@redhat.com \
    /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).