[libvirt] RFC New virDomainBlockPull API family to libvirt

Stefan Hajnoczi stefanha at gmail.com
Fri Jul 15 13:08:49 UTC 2011


On Fri, Jul 15, 2011 at 12:07 PM, Stefan Hajnoczi <stefanha at gmail.com> wrote:
> On Fri, Jul 15, 2011 at 12:05 PM, Kevin Wolf <kwolf at redhat.com> wrote:
>> Am 15.07.2011 12:50, schrieb Stefan Hajnoczi:
>>> On Thu, Jul 14, 2011 at 7:54 PM, Adam Litke <agl at us.ibm.com> wrote:
>>>>
>>>>
>>>> On 07/14/2011 05:33 AM, Stefan Hajnoczi wrote:
>>>>> On Thu, Jul 14, 2011 at 11:19 AM, Jiri Denemark <jdenemar at redhat.com> wrote:
>>>>>> On Thu, Jul 14, 2011 at 10:58:31 +0100, Stefan Hajnoczi wrote:
>>>>>>> On Thu, Jul 14, 2011 at 10:21 AM, Jiri Denemark <jdenemar at redhat.com> wrote:
>>>>>>>> On Wed, Jul 13, 2011 at 15:46:30 -0500, Adam Litke wrote:
>>>>>>>> ...
>>>>>>>>> /*
>>>>>>>>>  * BlockPull API
>>>>>>>>>  */
>>>>>>>>>
>>>>>>>>> /* An iterator for initiating and monitoring block pull operations */
>>>>>>>>> typedef unsigned long long virDomainBlockPullCursor;
>>>>>>>>>
>>>>>>>>> typedef struct _virDomainBlockPullInfo virDomainBlockPullInfo;
>>>>>>>>> struct _virDomainBlockPullInfo {
>>>>>>>>>     /*
>>>>>>>>>      * The following fields provide an indication of block pull progress.  @cur
>>>>>>>>>      * indicates the current position and will be between 0 and @end.  @end is
>>>>>>>>>      * the final cursor position for this operation and represents completion.
>>>>>>>>>      * To approximate progress, divide @cur by @end.
>>>>>>>>>      */
>>>>>>>>>     virDomainBlockPullCursor cur;
>>>>>>>>>     virDomainBlockPullCursor end;
>>>>>>>>> };
>>>>>>>>> typedef virDomainBlockPullInfo *virDomainBlockPullInfoPtr;
>>>>>>>> ...
>>>>>>>>> /**
>>>>>>>>>  * virDomainBlockPullAbort:
>>>>>>>>>  * @dom: pointer to domain object
>>>>>>>>>  * @path: fully-qualified filename of disk
>>>>>>>>>  * @flags: currently unused, for future extension
>>>>>>>>>  *
>>>>>>>>>  * Cancel a pull operation previously started by virDomainBlockPullAll().
>>>>>>>>>  *
>>>>>>>>>  * Returns -1 in case of failure, 0 when successful.
>>>>>>>>>  */
>>>>>>>>> int                 virDomainBlockPullAbort(virDomainPtr dom,
>>>>>>>>>                                             const char *path,
>>>>>>>>>                                             unsigned int flags);
>>>>>>>>>
>>>>>>>>> /**
>>>>>>>>>  * virDomainGetBlockPullInfo:
>>>>>>>>>  * @dom: pointer to domain object
>>>>>>>>>  * @path: fully-qualified filename of disk
>>>>>>>>>  * @info: pointer to a virDomainBlockPullInfo structure
>>>>>>>>>  * @flags: currently unused, for future extension
>>>>>>>>>  *
>>>>>>>>>  * Request progress information on a block pull operation that has been started
>>>>>>>>>  * with virDomainBlockPull().  If an operation is active for the given
>>>>>>>>>  * parameters, @info will be updated with the current progress.
>>>>>>>>>  *
>>>>>>>>>  * Returns -1 in case of failure, 0 when successful.
>>>>>>>>>  */
>>>>>>>>> int                 virDomainGetBlockPullInfo(virDomainPtr dom,
>>>>>>>>>                                               const char *path,
>>>>>>>>>                                               virDomainBlockPullInfoPtr info,
>>>>>>>>>                                               unsigned int flags);
>>>>>>>>>
>>>>>>>>> /**
>>>>>>>>>  * virConnectDomainEventBlockPullStatus:
>>>>>>>>>  *
>>>>>>>>>  * The final status of a virDomainBlockPull() operation
>>>>>>>>>  */
>>>>>>>>> typedef enum {
>>>>>>>>>     VIR_DOMAIN_BLOCK_PULL_COMPLETED = 0,
>>>>>>>>>     VIR_DOMAIN_BLOCK_PULL_FAILED = 1,
>>>>>>>>> } virConnectDomainEventBlockPullStatus;
>>>>>>>>>
>>>>>>>>> /**
>>>>>>>>>  * virConnectDomainEventBlockPullCallback:
>>>>>>>>>  * @conn: connection object
>>>>>>>>>  * @dom: domain on which the event occurred
>>>>>>>>>  * @path: fully-qualified filename of the affected disk
>>>>>>>>>  * @status: final status of the operation (virConnectDomainEventBlockPullStatus
>>>>>>>>>  *
>>>>>>>>>  * The callback signature to use when registering for an event of type
>>>>>>>>>  * VIR_DOMAIN_EVENT_ID_BLOCK_PULL with virConnectDomainEventRegisterAny()
>>>>>>>>>  */
>>>>>>>>> typedef void (*virConnectDomainEventBlockPullCallback)(virConnectPtr conn,
>>>>>>>>>                                                        virDomainPtr dom,
>>>>>>>>>                                                        const char *path,
>>>>>>>>>                                                        int status,
>>>>>>>>>                                                        void *opaque);
>>>>>>>>
>>>>>>>> Could these managing functions and event callback become general and usable by
>>>>>>>> other block operations such as block copy?
>>>>>>>
>>>>>>> Hi Jiri,
>>>>>>> Live block copy will certainly be possible using the streaming API.
>>>>>>> Before you start streaming you need to use the snapshot_blkdev command
>>>>>>> to create the destination file with the source file as its backing
>>>>>>> image.  You can then use the streaming API to copy data from the
>>>>>>> source file into the destination file.  On completion the source file
>>>>>>> is no longer needed.
>>>>>>
>>>>>> Well, I'm not talking about using the same API for block copy or implementing
>>>>>> block copy internally as block streaming. I'm talking about making GetInfo,
>>>>>> Abort and event callback general to be usable not only for block streaming or
>>>>>> block copy but also for other possible block operations in the future.
>>>>>>
>>>>>> The reason is that starting a block operation (streaming, copy, whatever) may
>>>>>> need different parameters so they should be different APIs. But once the
>>>>>> operation is started, we just need to know how far it got and we need the
>>>>>> ability to abort the job. So this can share the same APIs for all operations.
>>>>>> It doesn't make sense to require any block operation to provide their own set
>>>>>> of managing APIs.
>>>>>>
>>>>>> It's analogous to virDomainSave, virDomainMigrate, virDomainCoreDump. They are
>>>>>> all different jobs but all of them can be monitored and aborted using
>>>>>> virDomainGetJobInfo and virDomainAbortJob.
>>>>>
>>>>> I understand.  I can't comment on libvirt API specifics but yes,
>>>>> there's a similarity here and a chance we'll have other operations in
>>>>> the future too.
>>>>>
>>>>> I'm thinking things like compacting images, compressing images, etc.
>>>>
>>>> From a libvirt API perspective, I would only want to merge the abort and
>>>> info commands if the underlying qemu monitor commands are also merged.
>>>> Otherwise, we'll need to maintain state on which types of jobs are
>>>> active on which devices and the added complexity erases any potential
>>>> benefits IMO.
>>>>
>>>> Stefan, any chance that block operation info and cancellation could be
>>>> unified at the qemu level?
>>>
>>> The commands would become "block_job_cancel" and "info block-job".
>>>
>>> block_stream would start a job, which basically means:
>>> BlockJob {
>>>     BlockDriverState *bs; /* the block device */
>>>     BlockJobType type; /* BLOCK_JOB_STREAMING */
>>>     int64_t offset;    /* progress info */
>>>     int64_t end;
>>> };
>>>
>>> We probably want to generalize the offset/end pair to have no units.
>>> They are simply used to indicate progress information.  When the job
>>> completes offset == end.
>>>
>>> The BLOCK_STREAM_COMPLETED event also needs to be generalized to
>>> BLOCK_JOB_COMPLETED.
>>>
>>> This approach is reasonable although I do worry that we don't
>>> understand the requirements for future block device background jobs.
>>> For example, jobs that perform an operation on two block devices
>>> instead of just one.  With QMP we are extensible and can add fields
>>> for specific job types, so hopefully we can get by without finding the
>>> API inadequate for future block jobs.
>>>
>>> Kevin: What do you think about providing a job interface instead of
>>> tying the cancel and info operations specifically to block_stream?
>>
>> I guess it's a reasonable thing to do. We shouldn't overengineer here
>> and try to solve all problems in qemu at once, but as long as we're
>> basically talking about renaming what our current streaming/block copy
>> concept needs anyway, I don't see a problem.
>
> I would leave block_stream as-is because the job start function is
> where most of the variability comes in.  I think it's not worth doing
> a generic block_job_start function where you have to say
> type=streaming.
>
> /me is off to update the image streaming API wiki page (and have lunch).

The wiki is updated with block_job APIs and block_stream_set_speed:
http://wiki.qemu.org/Features/LiveBlockMigration/ImageStreamingAPI

Stefan




More information about the libvir-list mailing list