qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>, Peter Krempa <pkrempa@redhat.com>,
	qemu-devel@nongnu.org, qemu-block@nongnu.org
Subject: Re: [Qemu-devel] Non-flat command line option argument syntax
Date: Fri, 3 Feb 2017 16:57:23 +0000	[thread overview]
Message-ID: <20170203165722.GC4674@work-vm> (raw)
In-Reply-To: <87shnvhfwc.fsf@dusky.pond.sub.org>

* Markus Armbruster (armbru@redhat.com) wrote:
> "Dr. David Alan Gilbert" <dgilbert@redhat.com> writes:
> 
> > * Markus Armbruster (armbru@redhat.com) wrote:
> >> = Introduction =
> >> 
> >
> > <snip>
> >
> >> = Structured option argument syntax =
> >> 
> >> == JSON ==
> >> 
> >> The obvious way to provide the expressiveness of JSON on the command
> >> line is JSON.  Easy enough[2].  However, besides not being compatible,
> >> it's rather heavy on syntax, at least for simple cases.  Compare:
> >> 
> >>     -machine q35,accel=kvm
> >>     -machine '{ "type": "q35", "accel": "kvm"}'
> >> 
> >> It compares a bit more favourably in cases that use our non-flat hacks.
> >> Here's a flat list as KEY=VALUE,... with repeated keys, and as JSON:
> >> 
> >>     -semihosting-config enable,arg=eins,arg=zwei,arg=drei
> >>     -semihosting-config '{ "enable": true, "arg": [ "eins", "zwei", "drei" ] }'
> >> 
> >> Arbitrary nesting with dotted key convention:
> >> 
> >>     -drive driver=qcow2,file.driver=gluster,
> >>            file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
> >>            file.server.0.type=tcp,
> >>            file.server.0.host=1.2.3.4,
> >>            file.server.0.port=24007,
> >>            file.server.1.type=unix,
> >>            file.server.1.socket=/var/run/glusterd.socket
> >>     -drive '{ "driver": "qcow2",
> >>               "file": {
> >>                   "driver": "gluster", "volume": "testvol",
> >>                   "path": "/path/a.qcow2", "debug": 9,
> >>                   "server": [ { "type": "tcp",
> >>                                 "host": "1.2.3.4", "port": "24007"},
> >>                               { "type": "unix",
> >>                                 "socket": "/var/run/glusterd.socket" } ] } }'
> >
> > So while I generally hate JSON, the -drive dotted key syntax makes
> > me mad when it gets like this;  have a look
> > at the block replication and quorum setups especially, that can end up
> > with (from docs/COLO-FT.txt):
> >
> >   -drive if=virtio,id=primary-disk0,driver=quorum,read-pattern=fifo,vote-threshold=1,\
> >          children.0.file.filename=1.raw,\
> >          children.0.driver=raw -S
> >
> >    that's just way too many .'s to ever properly understand.
> > (I'm sure it used to be more complex).
> 
> Here's an idea to cut down on the dottery that drives you mad (and me
> too): if KEY starts with '.', combine it with a prefix of the previous
> one so that the result has the same number of name components.
> 
> Your example becomes
> 
>     -drive if=virtio,id=primary-disk0,driver=quorum,read-pattern=fifo,vote-threshold=1,\
>            children.0.file.filename=1.raw,.driver=raw -S
> 
> My example
> 
>      -drive driver=qcow2,file.driver=gluster,
>             file.volume=testvol,file.path=/path/a.qcow2,file.debug=9,
>             file.server.0.type=tcp,
>             file.server.0.host=1.2.3.4,
>             file.server.0.port=24007,
>             file.server.1.type=unix,
>             file.server.1.socket=/var/run/glusterd.socket
> 
> becomes
> 
>      -drive driver=qcow2,
>             file.driver=gluster,
>                 .volume=testvol,
>                 .path=/path/a.qcow2,
>                 .debug=9,
>             file.server.0.type=tcp,
>                          .host=1.2.3.4,
>                          .port=24007,
>             file.server.1.type=unix,
>                          .socket=/var/run/glusterd.socket
> 
> Mind, I'm not at all sure this is a *good* idea.  I suspect it's more
> magic than it's worth.

That is actually quite a nice compaction; it still feels pretty easy to read,
and doesn't use any more magic characters.

> >> Lines broken and indented for legibility; you need to join them for
> >> actual use.
> >
> > Why? What's a \n between friends for JSON?
> 
> You're right, the JSON works as is.  Only the KEY=VALUE example doesn't.
> 
> >> Once you do, both variants are basically illegible.  This
> >> is simply something that belongs into a config file rather than the
> >> command line.  In a config file, JSON would be a better choice.
> >> 
> >> There's also the -drive file=json:... syntax.  It's a bad fit for
> >> QemuOpts, because QemuOpts and JSON fight for the comma.  I'd show you
> >> if I could get it to work.
> >> 
> >> We obviously can't replace QemuOpts with JSON.  But accepting JSON in
> >> addition to QemuOpts is a debatable feature: it lets management
> >> applications reuse the code to build QMP arguments for option arguments.
> >> 
> >> Since structured option arguments are always dictionaries, a JSON option
> >> argument always starts with '{'.  If no QemuOpts argument can ever start
> >> with '{', accepting either QemuOpts or a JSON object is unambiguous.
> >> For a more detailed discussion of the following argument, see [3].
> >> 
> >> A QemuOpts argument normally starts with KEY.  We need to outlaw KEYs
> >> starting with '{'.  QAPI outlaws such names, see docs/qapi-code-gen.txt.
> >> QOM doesn't, but no such keys exist as far as I know.
> >> 
> >> QemuOpts permit abbreviating KEY=VALUE to just VALUE for one specific
> >> KEY (the "implied" key).  We need to limit this to KEYs whose VALUE
> >> can't start with '{'.  Most implied keys can't have such values.
> >> Troublemakers include qemu-img's use of implied "file" keys.  You'd have
> >> to say "file={my-tastelessly-named-file}" instead of just
> >> "{my-tastelessly-named-file}".
> >
> > What worries me a bit is building shell scripts which include ['s and {'s
> > tends to be painful.
> 
> No more than it already is if your builder copes with arbitrary
> filenames and such.  But point well taken.
> 
> > <snip>
> >
> >> === Structured values ===
> >> 
> >> The dotted key convention messes with KEY syntax to permit structured
> >> values.  Works, but the more conventional way to support structured
> >> values is a syntax for structured values.  
> >> 
> >> An obvious one is to use { KEY=VALUE, ...} for objects, and [ VALUE,
> >> ... ] for arrays.  Looks like this:
> >> 
> >>     -drive 'driver=quorum,
> >>             child=[{ driver=file, filename=disk1.img },
> >>                    { driver=host_device, filename=/dev/sdb },
> >>                    { driver=nbd, host=localhost } ]'
> >> 
> >> Again, lines broken and indented for legibility; you need to join them
> >> for actual use.
> >> 
> >> There's a syntactic catch, though: a value of the form [ ... ] can
> >> either be an array or a string.  Which one it is depends on the type of
> >> the key.  To parse this syntax, you need to know the types, unlike JSON
> >> or traditional QemuOpts.  Unless we outlaw strings starting with '{' or
> >> '[', which feels impractical.
> >
> > I don't understand why [ could imply a string.
> 
> Consider
> 
>     -drive 'driver=quorum,
>             child=[{ driver=file, filename={"foolish":"name"} },
>                    { driver=host_device, filename=/dev/sdb },
>                    { driver=nbd, host=[::1] } ]'
> 
> Three KEY=VALUE have their VALUE start with '[' or '{':
> 
> * child=[{ driver=file, ...
> 
>   This is an array, not a string, because child is an array.
> 
> * host=[::1]
> 
>   This is a string, not an array containing the string "::1", because
>   host is a string.

Why is that accepted as valid input? Can't that just spit a
'I wanted a string not an array' ?

> * filename={"foolish":"name"}
> 
>   This is a string, not an object, because filename is a string.
> 
> Clearer now?
> 
> >> But wait, there's another syntactic catch: in traditional QemuOpts, a
> >> value ends at the next unescaped ',' or '\0'.  Inside an object, it now
> >> also ends at the next unescaped '}', and inside an array, at the next
> >> unescaped ']'.  Or perhaps at the next space (the example above assumes
> >> it does).  That means we either have to provide a way to escape '}', ']'
> >> and space, or find another way to delimit string values, say require '"'
> >> around strings whenever the string contains "funny" characters.
> >
> > How about a tighter rule that if you've got a structured value -
> > i.e. you're inside either of [ or {, then you must " all strings
> > (except keys that we keep clean).
> 
> Matter of taste.
> 
> Regardless, we need a way to escape '"'.  Doubling it would be
> consistent with the existing escape of ','.

Doubling for escape feels hideous, especially for ".

Dave

> >> So, if escaped ',' wasn't ugly and confusing enough for you...
> >> 
> >> === Comparison ===
> >> 
> >> In my opinion, dotted keys are weird and ugly, but at least they don't
> >> add to the quoting mess.  Structured values look better, except when
> >> they do add to the quoting mess.
> >> 
> >> I'm having a hard time deciding which one I like less :)
> >> 
> >> Opinions?  Other ideas?
> >
> > Dave
> >
> >> 
> >> 
> >> 
> >> 
> >> [1] [PATCH v14 00/21] QAPI/QOM work for non-scalar object properties
> >> (actually v15)
> >> Message-Id: <1475246744-29302-1-git-send-email-berrange@redhat.com>
> >> http://lists.gnu.org/archive/html/qemu-devel/2016-09/msg08238.html
> >> 
> >> [2] [RFC PATCH] block: Crude initial implementation of -blockdev
> >> Message-Id: <1485968933-9162-1-git-send-email-armbru@redhat.com>
> >> http://lists.gnu.org/archive/html/qemu-devel/2017-02/msg00182.html
> >> 
> >> [3] Message-ID: <87h989ncse.fsf@dusky.pond.sub.org>
> >> http://lists.gnu.org/archive/html/qemu-devel/2016-10/msg04046.html
> >> 
> > --
> > Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

  reply	other threads:[~2017-02-03 16:57 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-02 19:42 [Qemu-devel] Non-flat command line option argument syntax Markus Armbruster
2017-02-02 20:06 ` Eric Blake
2017-02-02 20:23 ` Eric Blake
2017-02-03  7:57   ` Markus Armbruster
2017-02-02 20:27 ` Dr. David Alan Gilbert
2017-02-03  7:50   ` Markus Armbruster
2017-02-03 16:57     ` Dr. David Alan Gilbert [this message]
2017-02-04  9:44       ` Markus Armbruster
2017-02-06 10:20         ` Dr. David Alan Gilbert
2017-02-03 20:02     ` [Qemu-devel] [Qemu-block] " Max Reitz
2017-02-04  9:45       ` Markus Armbruster
2017-02-04 10:03         ` [Qemu-devel] " Paolo Bonzini
2017-02-04 11:52           ` Markus Armbruster
2017-02-04 12:43             ` Paolo Bonzini
2017-02-03 10:03 ` Daniel P. Berrange
2017-02-03 11:13   ` Markus Armbruster
2017-02-03 12:37 ` Peter Krempa
2017-02-03 13:53   ` Markus Armbruster
2017-02-03 17:25 ` Richard W.M. Jones
2017-02-04  9:51   ` Markus Armbruster
2017-02-05 20:46     ` [Qemu-devel] [Qemu-block] " Max Reitz
2017-02-03 20:28 ` Max Reitz
2017-02-04  9:56   ` Markus Armbruster
2017-02-04 12:21 ` [Qemu-devel] " Fam Zheng
2017-02-04 12:44   ` Paolo Bonzini
2017-02-04 13:02     ` Fam Zheng
2017-02-04 13:35   ` Markus Armbruster
2017-02-04 14:10     ` Fam Zheng
2017-02-06  6:24       ` Markus Armbruster
2017-02-06 11:08   ` Daniel P. Berrange
2017-02-06  6:57 ` Markus Armbruster
2017-02-06 13:23 ` Kevin Wolf
2017-02-06 15:36   ` Markus Armbruster
2017-02-06 16:33     ` Daniel P. Berrange
2017-02-06 17:24       ` Markus Armbruster
2017-02-06 17:50         ` Daniel P. Berrange
2017-02-06 18:56           ` Markus Armbruster
2017-02-06 17:38     ` Paolo Bonzini
2017-02-06 18:12       ` Markus Armbruster
2017-02-06 21:52         ` Paolo Bonzini
2017-02-07  7:02           ` Markus Armbruster
2017-02-07  9:26     ` Kevin Wolf
2017-02-24 16:04 ` Markus Armbruster
2017-02-24 16:39   ` Daniel P. Berrange
2017-02-24 17:17     ` Eric Blake
2017-02-24 19:15       ` Markus Armbruster
2017-02-27 10:27 ` Markus Armbruster
2017-02-27 10:59   ` Kevin Wolf
2017-02-27 13:36     ` Markus Armbruster
2017-02-27 19:47       ` Eric Blake
2017-02-28  8:24         ` Markus Armbruster
2017-02-27 19:43   ` Eric Blake
2017-02-28  8:41     ` Markus Armbruster
2017-03-01  9:24 ` Markus Armbruster
2017-03-21  8:40 ` 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=20170203165722.GC4674@work-vm \
    --to=dgilbert@redhat.com \
    --cc=armbru@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pkrempa@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.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).