[Libguestfs] [PATCH nbdkit v2 03/10] python: Implement nbdkit API version 2.
Eric Blake
eblake at redhat.com
Fri Nov 22 21:30:21 UTC 2019
On 11/22/19 3:14 PM, Richard W.M. Jones wrote:
>>> @@ -54,20 +61,20 @@ def get_size(h):
>>> return len(disk)
>>> -def pread(h, count, offset):
>>> +def pread(h, count, offset, flags):
>>> global disk
>>> return disk[offset:offset+count]
>>
>> Do we really want to be passing 'flags' as an integer that the
>> python script must decode?
>
> While I'm no Python programmer, it does look as if existing Python
> core APIs are happy to use bitmasks, eg:
>
> https://docs.python.org/3/library/os.html#os.open
>
> and this is also easy to implement and keeps it similar to the C API.
Fair enough. I'm just making sure that our Python interface is at least
idiomatic to a Python programmer, rather than blatantly being a naive
translation of a C programmer.
>
>>> - def pwrite(h, buf, offset):
>>> + def pwrite(h, buf, offset, flags):
>>> length = len (buf)
>>> # no return value
>>> The body of your C<pwrite> function should write the C<buf> string to
>>> the disk. You should write C<count> bytes to the disk starting at
>>> -C<offset>.
>>> +C<offset>. C<flags> may contain C<nbdkit.FLAG_FUA>.
>>
>> Should we mention that FLAG_FUA is only set if the python callback
>> can_fua returned 1? Or is that somewhat redundant with the fact
>> that we already document that someone writing a python plugin should
>> be familiar with the docs for C plugins, and that guarantee is
>> already in the C plugin docs?
>
> I think it would be better if we simply referred back to the C
> documentation to avoid duplication. Also an advantage of using
> bitmasks. That does require a rather larger change to the
> documentation though.
Pointing to the C docs, and focusing on just the bindings-induced
differences, is fine.
>
>>> static int
>>> -py_pwrite (void *handle, const void *buf,
>>> - uint32_t count, uint64_t offset)
>>> +py_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
>>> + uint32_t flags)
>>> {
>>> PyObject *obj = handle;
>>> PyObject *fn;
>>> @@ -515,9 +546,19 @@ py_pwrite (void *handle, const void *buf,
>>> if (callback_defined ("pwrite", &fn)) {
>>> PyErr_Clear ();
>>> - r = PyObject_CallFunction (fn, "ONL", obj,
>>> - PyByteArray_FromStringAndSize (buf, count),
>>> - offset, NULL);
>>> + switch (py_api_version) {
>>> + case 1:
>>> + r = PyObject_CallFunction (fn, "ONL", obj,
>>> + PyByteArray_FromStringAndSize (buf, count),
>>> + offset, NULL);
>>
>> Here, we could assert (flags == 0) (the FUA flag should not be set
>> if the plugin uses v1 API).
>
> Is that true? The plugin asserts that it wants the v1 API, but we are
> still using the v2 C API, whatever the plugin asks for?
Hmm. If the user implements a 'can_fua' callback that returns 1 even
though they forgot to declare 'api_version', then the flag can indeed be
set. Perhaps that means our 'can_fua' C wrapper should have a version
1/2 difference in behavior (in v1, raise an error reminding the user to
fix their plugin to declare 'api_version', in v2 pass back the result),
so that we could indeed then use the assert with a guarantee that it
will not trigger on an arbitrary plugin.
>
> I'm cautious about adding asserts unless they can never happen now or
> in the future, because we don't really want an assert() happening on a
> customer site running virt-v2v with the rhv-upload Python plugin.
Understood.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3226
Virtualization: qemu.org | libvirt.org
More information about the Libguestfs
mailing list