The “Try” in the subject of this series means more or less the same as
the “Try” in the subject line of
http://lists.nongnu.org/archive/html/qemu-block/2018-05/msg00061.html .

The difference is that it’s not so important here, because the worst
outcome is that in very narrow edge cases[1] (e.g. you trying to use
password-secret for rbd) we fail to generate a properly typed json:{}
filename -- but that is no regression over what we currently have.  In
the vast majority of cases[1], this series will result in proper
typing.

Or, well, I should add that I’m not quite sure about all the edge
cases[1], solely because the current bdrv_refresh_filename() code is a
mess, especially when it comes to gathering the blockdev options.  But
I do know that after my series to address that (“block: Fix some
filename generation issues”), it only comes down to a very small number
of edge cases (the only hard edge case is rbd’s =keyvalue-pairs, but
that is kaput anyway).[1]

But since this series does not have any hard requirement on that other
one, I decided to send it independently.


[1] You might have noticed a number of [1]s above.  This is because the
above text is as it was in a version of this series with only five
patches in it.  Then I noticed a not-so-edge case where converting to
QAPI broke down: qcow(2) encryption.  Since qcow and qcow2 now support
both the old AES and luks encryption, and every encryption type may
offer its own runtime options, you now have a flat union there (under
“encrypt”) which is discriminated based on encrypt.format.
Now the qcow2 driver can of course detect the format from the image
header, so you don’t really have to specify it.  In fact, when your
options don’t go through QAPI, you actually don’t have to.  So this is
exactly the not-so-edge case I was talking about.

QAPI cannot parse encrypt before it knows encrypt.format.  So it’s much
too late when the qcow2 driver detects encrypt.format in its
.bdrv_open() plementation.

I’m more than happy to take alternative suggestions, but this is an
issue we really cannot ignore (unlike =keyvalue-pairs), so the two
solutions I came up with are:

(1) Say auto-detection was a bad idea and make encrypt.format mandatory,
    even without QAPI.  This is always a possibility, but it does seem
    kind of cumbersome to users, so I wanted to explore the other option
    first, not knowing how deep into the rabbit hole that would lead.

(2) Allow flat union discriminators to be optional.  Since both AES and
    luks encryption in practice only allow a key-secret option, we can
    add a new runtime encryption pseudo-type, which is “from-image” that
    only allows such a key-secret option.  Now, when the user does not
    specify encrypt.format, the format is assumed to be “from-image”
    which means that you can specify a key-secret and qcow/qcow2 will
    figure out what encryption to use.
    This allows to retain compatibility with the current interface, but
    it also means this series exploded, and maybe the idea is
    universally hated.
    One issue I can see with this approach is how it would fare with new
    encryption types added; specifically, what if we add some encryption
    type that does not have a key-secret but something else?  Do we add
    that something else to from-image and make everything optional?  Or
    do we require users to explicitly specify the encryption type for
    such a new type when it is not compatible with from-image?
    In any case, one thing we have to watch out for from now on is that
    drivers must not allow options to be optional that are mandatory in
    the QAPI schema.
    More generally, we have to make sure that the driver’s interface on
    -drive is compatible to QAPI.  But I guess everybody knows that, so
    it’s good to be a bit more specific and say that this doesn’t just
    mean that options must match.  Mandatoriness must match also.

So, OK, obviously I chose solution (2) for now.  What this means is that
in this series:

- The QAPI code generator is modified to allow optional discriminators
  for flat unions.  In such a case, a default-variant must be supplied
  to choose when the discriminator value is not present on the wire.
  - Accordingly, documentation, tests, and introspection are adjusted.

- This is used to make qcow’s and qcow2’s encrypt.format parameter
  optional.  It now defaults to “from-image” which is a new
  pseudo-format that allows a key-secret to be given, and otherwise
  leaves it to the format driver to determine the encryption format.

- qdict_stringify_for_keyval() is added, as already proposed/hinted at
  in the rbd QAPI discussion.  This includes movement of many
  block-specific QDict function declarations into an own header, as
  suggested by Markus.

- json:{} filenames are attempted to be typed correctly when they are
  generated, by running bs->full_open_options through a healthy mix of
  qdict_flatten(), qdict_stringify_for_keyval(), qdict_crumple(), the
  keyval input visitor for BlockdevOptions, and the output visitor.
  This may not always work but I hope it usually will.  Fingers crossed.
  (At least it won’t make things worse.)

- Tests, tests, tests.


(Yes, I know that “In this series tests, tests, tests.” is not a
 sentence.)


Max Reitz (13):
  qapi: Add default-variant for flat unions
  docs/qapi: Document optional discriminators
  tests: Add QAPI optional discriminator tests
  qapi: Formalize qcow2 encryption probing
  qapi: Formalize qcow encryption probing
  block: Add block-specific QDict header
  qdict: Add qdict_stringify_for_keyval()
  tests: Add qdict_stringify_for_keyval() test
  qdict: Make qdict_flatten() shallow-clone-friendly
  tests: Add QDict clone-flatten test
  block: Try to create well typed json:{} filenames
  iotests: Test internal option typing
  iotests: qcow2's encrypt.format is now optional

 docs/devel/qapi-code-gen.txt                       | 21 +++++-
 tests/Makefile.include                             |  3 +
 qapi/block-core.json                               | 72 ++++++++++++++++--
 qapi/introspect.json                               |  8 ++
 ...ion-optional-discriminator-invalid-default.json | 12 +++
 ...at-union-optional-discriminator-no-default.json | 11 +++
 .../flat-union-optional-discriminator.json         |  4 +-
 .../flat-union-superfluous-default-variant.json    | 11 +++
 include/block/qdict.h                              | 37 +++++++++
 include/qapi/qmp/qdict.h                           | 17 -----
 block.c                                            | 70 ++++++++++++++++-
 block/gluster.c                                    |  1 +
 block/iscsi.c                                      |  1 +
 block/nbd.c                                        |  1 +
 block/nfs.c                                        |  1 +
 block/parallels.c                                  |  1 +
 block/qcow.c                                       |  1 +
 block/qcow2.c                                      |  1 +
 block/qed.c                                        |  1 +
 block/quorum.c                                     |  1 +
 block/rbd.c                                        |  1 +
 block/sheepdog.c                                   |  1 +
 block/snapshot.c                                   |  1 +
 block/ssh.c                                        |  1 +
 block/vhdx.c                                       |  1 +
 block/vpc.c                                        |  1 +
 block/vvfat.c                                      |  1 +
 block/vxhs.c                                       |  1 +
 blockdev.c                                         |  1 +
 qobject/qdict.c                                    | 81 ++++++++++++++++++--
 tests/check-qdict.c                                | 88 ++++++++++++++++++++++
 tests/check-qobject.c                              |  1 +
 tests/test-replication.c                           |  1 +
 util/qemu-config.c                                 |  1 +
 scripts/qapi/common.py                             | 57 +++++++++++---
 scripts/qapi/doc.py                                |  8 +-
 scripts/qapi/introspect.py                         | 10 ++-
 scripts/qapi/visit.py                              | 33 +++++++-
 ...nion-optional-discriminator-invalid-default.err |  1 +
 ...ion-optional-discriminator-invalid-default.exit |  1 +
 ...nion-optional-discriminator-invalid-default.out |  0
 ...lat-union-optional-discriminator-no-default.err |  1 +
 ...at-union-optional-discriminator-no-default.exit |  1 +
 ...lat-union-optional-discriminator-no-default.out |  0
 .../flat-union-optional-discriminator.err          |  1 -
 .../flat-union-optional-discriminator.exit         |  2 +-
 .../flat-union-optional-discriminator.out          | 15 ++++
 .../flat-union-superfluous-default-variant.err     |  1 +
 .../flat-union-superfluous-default-variant.exit    |  1 +
 .../flat-union-superfluous-default-variant.out     |  0
 tests/qapi-schema/test-qapi.py                     |  2 +
 tests/qemu-iotests/059.out                         |  2 +-
 tests/qemu-iotests/087                             |  2 -
 tests/qemu-iotests/089                             | 25 ++++++
 tests/qemu-iotests/089.out                         |  9 +++
 tests/qemu-iotests/099.out                         |  4 +-
 tests/qemu-iotests/110.out                         |  2 +-
 tests/qemu-iotests/198.out                         |  4 +-
 tests/qemu-iotests/207.out                         | 10 +--
 59 files changed, 580 insertions(+), 68 deletions(-)
 create mode 100644 
tests/qapi-schema/flat-union-optional-discriminator-invalid-default.json
 create mode 100644 
tests/qapi-schema/flat-union-optional-discriminator-no-default.json
 create mode 100644 
tests/qapi-schema/flat-union-superfluous-default-variant.json
 create mode 100644 include/block/qdict.h
 create mode 100644 
tests/qapi-schema/flat-union-optional-discriminator-invalid-default.err
 create mode 100644 
tests/qapi-schema/flat-union-optional-discriminator-invalid-default.exit
 create mode 100644 
tests/qapi-schema/flat-union-optional-discriminator-invalid-default.out
 create mode 100644 
tests/qapi-schema/flat-union-optional-discriminator-no-default.err
 create mode 100644 
tests/qapi-schema/flat-union-optional-discriminator-no-default.exit
 create mode 100644 
tests/qapi-schema/flat-union-optional-discriminator-no-default.out
 create mode 100644 tests/qapi-schema/flat-union-superfluous-default-variant.err
 create mode 100644 
tests/qapi-schema/flat-union-superfluous-default-variant.exit
 create mode 100644 tests/qapi-schema/flat-union-superfluous-default-variant.out

-- 
2.14.3


Reply via email to