----- Original Message -----
> Dan rightly suggested I'd be more specific about what the task system
> is
> instead of what the task system isn't.
> The problem is that I'm not completely sure how it's going to work.
> It also depends on the events mechanism.
> This is my current working draft:
> TaskInfo:
> id string
> methodName string
> kwargs json-object (string keys variant values) *filtered to remove
> sensitive
>                                                  information
> getRunningTasks(filter string, filterType enum{glob, regexp})
> Returns a list of TaskInfo of all tasks that their id's match the
> filter
> That's it, not even stopTask()

So for each verb we need to implement a specific 'cancel' op if relevant?
e.g. copyImage -> cancelCopyImage ? (or just deleteImage on the target image in 
this case?)
for migrateVM -> cancelMigrateVM? etc.

> As explained, I would like to offload handling to the subsystems.
> In order to make things easier for the clients every subsystem can
> choose a
> filed of the object to be of type OperationInfo.
> This is a generic structure that the user has a generic way to track
> all tasks
> on all subsystem with a report interface. The extraData field is for
> subsystem
> specific data. This is where the storage subsystem would put, for
> example,
> imageState (broken, degraded, optimized) data.
> OperationInfo:
> operationDescription string - something out of an agreed enum of
> strings
>                               vaguely describing the operation at
>                               hand for
>                             example "Copying", "Merging", "Deleting",
>                             "Configuring", "Stopped", "Paused", ....
>                             They must be known to the client so it can in
>                             turn translate it in the UI. The also have to
>                             remain relatively vague as they are part of the
>                             interface meaning that new values will break old
>                             clients so they have to be reusable.
> stageDescription - Similar to operation description in case you want
> more
>                    granularity, optional.
> stage (int, int) - (5, 10) means 5 out of 10. 1 out of 1 implies the
> UI to not
>                    display stage widgets.
> percentage - 0-100, -1 means unknown.

I'm assuming this is not overall percentage but relative to current stage?

> lastError - (code, message) the same errors that can return for
> regular calls
> extraData - json-object
> For example creatVM will return once the object is created in VDSM.
> getVmInfo() would return, amongst other things, the operation info.
> For the case of preparing for launch it will be:
>   {"Creating", "configuring", (2, 4), 40, (0, ""),
>    {state="preparing for launch"}}
> In the case of VM paused on EIO:
>   {"Paused", "Paused", (1, 1), -1, (123, "Error writing to disks"),
>    {state="paused"}}
> Migration is a tricky one, it will be reported as a task while it's
> in progress
> but all the information is available on the image operationInfo.
> In the case of Migration:
>   {"Migration", "Configuring", (1, 3), -1, (0, ""),
>   {status="Migrating"}}

Since you wrote 'image' I'm assuming you're referring to storage migration here?
So the migrate command is successful the moment it starts? (or even a bit 
before, once it persisted info or something) and then to query the state of the 
migration user needs to call 'image operationInfo'?

> For StorageConnection this is somewhat already the case but in
> simplified
> version.
> If you want to ask about any other operation I'd be more then happy
> to write my
> suggestion for it.
> Subsystems have complete freedom about how to set up the API.
> For Storage you have Fixes() to start\stop operations.


> Gluster is pretty autonomous once operations have been started.
> Since operations return as soon as they are registered (persisted) or
> fail to
> register, it makes synchronous programming a bit clunky.
> vdsm.pauseVm(vmId) doesn't return when the VM is paused but when VDSM
> committed
> it will try to pause it. This means you will have to poll in order to
> see if
> the operation finished. For gluster, as an example, this is the only
> way we
> can check that the operation finished.
> For stuff we have a bit more control over vdsm will fire events using
> json-rpc
> notifications sent to the clients. The will be in the form of:
> {"method": "alert", "params": {
>   "alertName": <subsystem>(.<objectType>)?.<object>.(<subobject>.,
>   ...),
>   "operationInfo", OperationInfo}
> }
> The user can register to recive events using a glob or a regexp.
> registering to vdsm.VM.* pop every time any VM has changed stage.
> This means that whenever the task finishes, fails or gains
> significance progress
> and VDSM is there to track it, an event will be sent to the client.
> This means that the general flow is.
> # Register operation
> vmID = best_vm
> host.VM.pauseVM(vmID)
> while True:
>     opInfo = None
>     try:
>        event = host.waitForEvent("vdsm.VM.best_vm", timeout=10)
>        opInfo = event.opInfo
>     except VdsmDisconnectionError:
>        host.waitForReconnect()
>        host.vm.getVmInfo(vmID)  # Double check that we didn't miss
>        the event
>        continue
>     except Timeout:
>        # This is a long operation, poll to see that we didn't miss
>        any event
>        # but more commonly, update percentage in the UI to show
>        progress.
>        vmInfo = host.vm.getVmInfo(vmID)
>        opInfo = vmInfo.operationInfo
>     if opInfo.stage.number != op.stage.total:
>        # Operation in progress
>        updateUI(opInfo)
>     else:
>        # Operation completed
>        # Check that the state is what we expected it to be.
>        if oInfo.extraData.state == "paused":
>           return SUCCESS
>        else:
>           return opInfo.lastError
> vdsm.waitForEvent(filterm, timeout) is a client side libvdsm helper
> operation.
> Clients that access the raw API need to create thir own client side
> code to
> filter out events and manage their distribution. I'm open to also
> defining
> server side filters but I'm not sure whether it's worth it or just
> having
> it be a boolean (all events or none) is sufficient.
> This is a very simplified example but the general flow is clear.
> Even if the connection is lost for 1 second or 4 days, the code
> still works. Further more, the user can wait for multiple operations
> in the same thread using:
>   host.waitForEvent("vdsm.VM.(best_vm_ever|not_so_good_vm)")
> This means that the client can wait for a 100 VMs or all VMs (using
> wildecards)
> in a mechanism similar "poll()" with minimal overhead. This also
> means that if
> The fact that operations are registered means that even if
> connections is lost
> due to VDSM crashing or the network crashing, the manager doesn't
> need to care
> one the original command returns as it know the operation registered.
> This doesn't mean that every operation must retry forever. How
> persistent
> every method is can and should change between the different
> operations.
> Also, it means that manager that didn't initiate an operation track
> it in
> the same way as those that did. This makes clustered managers a lot
> easier
> to implement as if one goes down a second one can more or less
> immediately with
> minimal extra code.
> _______________________________________________
> vdsm-devel mailing list
> vdsm-devel@lists.fedorahosted.org
> https://lists.fedorahosted.org/mailman/listinfo/vdsm-devel
vdsm-devel mailing list

Reply via email to