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.
|