Asynchronous Methods
All asynchronous methods in the Parallels Python API return an instance of the
prlsdkapi.Job
class. A
Job
object is a reference to the background job that the asynchronous method has started. A job is executed in the background and may take some time to finish. In other languages, asynchronous jobs are usually handled using
callbacks
(event handlers).
Unfortunately, callbacks are not available in the Parallels Python API. You have two ways of handling asynchronous jobs in your application. The first one consists of implementing a loop and checking the status of the asynchronous job in every iteration. The second approach involves the main thread suspending itself until the job is finished (essentially emulating a synchronous operation). The following describes each approach in detail.
Checking the job status
The
prlsdkapi.Job
class provides the
get_status
method that allows to determine whether the job is finished or not. The method returns one of the following constants:
prlsdkapi.prlsdk.consts.PJS_RUNNING
-- indicates that the job is still running.
prlsdkapi.prlsdk.consts.PJS_FINISHED
-- indicates that the job is finished.
prlsdkapi.prlsdk.consts.PJS_UNKNOWN
-- the job status cannot be determined for unknown reason.
By evaluating the code returned by the
prlsdkapi.Job.get_status
method, you can determine whether you can process the results of the job or still have to wait for the job to finish. The following code sample illustrates this approach.
# Start the virtual machine.
job = vm.start()
# Loop until the job is finished.
while True:
status = job.get_status()
if job.get_status() ==
prlsdkapi.prlsdk.consts.
PJS_FINISHED:
break
The scope of the loop in the example above doesn't have to be local of course. You can check the job status in the main program loop (if you have one) or in any other loop, which can be a part of your application design. You can have as many jobs running at the same time as you like and you can check the status of each one of them in the order of your choice.
Suspending the main thread
The
prlsdkapi.Job
class provides the
wait
method that can be used to suspend the execution of the main thread until the job is finished. The method can be invoked as soon as the
Job
object is returned by the original asynchronous method or at any time later. The following code snippet illustrates how it is accomplished.
# Start the virtual machine. This is an asynchronous call.
job = vm.start()
# Suspend the main thread and wait for the job to complete.
result = job.wait()
# The job is now finished and our program continues...
vm_config = vm.get_config()
print vm_config.get_name() + " was started."
You can also execute both the original asynchronous method and the
Job.wait
method on the same line without obtaining a reference to the
Job
object, as shown in the following example. Please note that if you do that, you will not be able to use any of the other methods of the
Job
class that can be useful in certain situations. The reason is, this type of method invocation returns the
prlsdkapi.Result
object containing the results of the operation, not the
Job
object (the
Result
class is described in the
Obtaining the job result
subsection below). It it still a perfectly valid usage that simplifies the program and reduces the number of lines in it.
# Start a virtual machine, wait for the job to complete.
vm.start().wait()
Obtaining the job results
Asynchronous methods that are used to perform actions of some sort (e.g. start or stop a virtual machine) don't usually return any data to the caller. Other asynchronous methods are used to obtain data from the Parallels Service side. The data is usually returned as an object or a list of objects. A good example would be a
prlsdkapi.Vm
object (virtual machine), a list of which is returned by the
prlsdkapi.Server.get_vm_list
asynchronous method. The data is not returned to the caller directly. It is contained in the
prlsdkapi.Result
object, which must be obtained from the
Job
object using the
Job.get_result
method. The
prlsdkapi.Result
class is a container that can contain one or more objects or strings depending on the operation that populated it. To determine the number of objects that it contains, the
Result.get_params_count
method must be used. To obtain an individual object, use the
get_param_by_index
method passing an index as a parameter (from 0 to count - 1).When an asynchronous operation returns a single object, the
get_param
method can be used. Strings are obtained in the similar manner using the corresponding methods of the
Result
class (
get_param_by_index_as_string
,
get_param_as_string
).
The following code snippet shows how to execute an asynchronous operation and then obtain the data from the
Job
object. In this example, we are obtaining the list of virtual machines registered with the Parallels Service.
# Obtain the virtual machine list.
# get_vm_list is an asynchronous method that returns
# a prlsdkapi.Result object containing the list of virtual machines.
job = server.get_vm_list()
job.wait()
result = job.get_result()
# Iterate through the Result object parameters.
# Each parameter is an instance of the prlsdkapi.Vm class.
for i in range(result.get_params_count()):
vm = result.get_param_by_index(i)
# Obtain the prlsdkapi.VmConfig object containing the virtual machine
# configuration information.
vm_config = vm.get_config()
# Get the name of the virtual machine.
vm_name = vm_config.get_name()
Other useful Job methods
The Job class provides other useful methods:
get_ret_code
-- obtains the asynchronous operation return code. On asynchronous operation completion, the job object will contain a return code indicating whether the operation succeeded or failed. Different jobs may return different error codes. The most common codes are
prlsdkapi.prlsdk.consts.PRL_ERR_INVALID_ARG
(invalid input parameters were specified during the asynchronous method invocation) and
prlsdkapi.prlsdk.consts.PRL_ERR_SUCCESS
(method successfully completed).
cancel
-- attempts to cancel a job that is still in progress. Please note that not all jobs can be canceled.
Asynchronous methods throw the
prlsdkapi.PrlSDKError
exception. For more information on exceptions, see the
Error Handling
section
.
|