AXL with Python

Now that you have discovered how to interact with the AXL API by using SoapUI to execute against the WSDL-defined API methods, you may be wondering how to overcome the challenge of programmatically building these requests' payloads and parsing their responses. Good news: this is where a Python library named zeep comes to our aid. The Zeep library, which can be downloaded from https://pypi.org/project/zeep/, itself depends on a few more Python libraries, such as lxml and requests to list a few. Collectively these Python libraries make our automation development efforts much easier. We will gently introduce you to these Python libraries before diving deep into them as you build the provisioning portal.

You will now navigate to your development environment where a web-based VS Code is running. You will start with executing the same listPhone AXL method that you used with SoapUI, but this time you will use Python code. The six tasks you will accomplish in this section are:

  1. AXL client setup
  2. List Phones
  3. Update a Phone
  4. Apply Phone Configuration
  5. Get Phone Details
  6. Add a Phone

Follow these steps to perform the above listed tasks:

Step 1 - AXL Client Setup

  1. Access your VS Code instance: https://dev1.pod6.col.lab:8443
  2. Click the Explorer icon at left, and you see a list of folders and files.
  3. Navigate to expand the examples folder and click to open soap_axl.py. You now have the file open for editing.

  4. Here is a basic Python script skeleton that you will use to execute SOAP AXL API requests using the zeep library. The Python environment on your development server has zeep and all other required libraries installed using the pip tool. Start with importing the zeep library to the sample Python script. Click the Copy button next to the highlighted line and paste it into your file.

  5. Next, create a few constant variables that you will use to connect and authenticate to your Pod's CUCM AXL API.

    Copy and paste your Pod's CUCM hostname, admin username and password into your file.

  6. In your development workspace, we have already downloaded the AXL WSDL files for you. Create another constant variable for the AXL_WSDL_File. You will use this WSDL file location variable to initialize our zeep client. Paste the following highlighted line it into the file.

  7. You will use the session object from the requests Python library to handle authentication, certificate validation (or not), and persist cookie caching across API requests.

    In this lab environment we are not using CA signed (valid) certificates on the CUCM server. In order to allow the Python script to establish SSL connection you need to disable SSL certificate verification for the sessions. Disabling SSL certificate validation is not recommended in production environments, hence there will be a warning printed in your console every time an insecure request is made. You will disable this warning as well.

    Finally you will configure the authentication type and credentials that will be used throughout the session. The script will utilize the HTTP Basic authentication method and the CUCM_USERNAME and CUCM_PASSWORD variables that you have created earlier.

    The following block of code will first create the session instance, then disable SSL Certificate verification and configure basic authentication. Paste the following highlighted lines it into your file.

  8. For debugging and troubleshooting purposes, you may need to inspect the SOAP envelope content that is being sent to CUCM and the corresponding responses. The zeep library comes with a built-in History plugin that makes it easier for you to inspect the payloads. Create an instance of zeep HistoryPlugin to achieve this. Paste the following into your file.

  9. You are now ready to create the zeep.Client instance that will greatly simplify sending and receiving AXL methods to/from CUCM. You will use the AXL_WSDL_FILE variable, session object, and the history plugin object to create the client instance. Paste the following into your file.

  10. The final step before you can use the zeep client is to create a new ServiceProxy object named service. The AXL WSDL file you downloaded from CUCM defaults the endpoint url to https://CCMSERVICENAME:8443/axl/ and needs to be updated to reflect your Pod's CUCM_ADDRESS. This configuration is the same as what you did with SoapUI under AXLAPIBinding --> Service Endpoints configuration. As you create a new service object using the zeep.client create_service method, you will utilize the formatted string (f-strings) literal with the CUCM_ADDRESS variable you defined earlier to set https://cucm1a.pod6.col.lab:8443/axl/ as the AXLAPIBinding endpoint url. Paste the following into your file.

Step 2 - List Phones with Python

You are now ready to use the newly created and fully configured service object that has all the available AXL API methods located in the WSDL file such as listPhones, very much like the SoapUI application you used earlier. Start by using the same listPhones method but this time with the Python script examples/soap_axl.py you have been working on.

  1. Recall the last request payload you sent when using SoapUI to request listPhones AXL API method.

    The listPhone method requires the following arguments: searchCriteria and returnedTags. SoapUI auto generated AXL method Requests can help identify the arguments and the data structure you must supply to the service.listPhone method.

    Create the following variables that you will pass as arguments to the listPhones method. Paste the following into your file.
  2. You now have everything you need to execute the listPhone method via Python. Before proceeding, take a look at how to identify the arguments and the data structures that must be passed to the service.listPhone method. The left side shows the XML as you would see it in SoapUI and the other boxes show how those pieces correspond to the various parts of the Python code. You can derive this same information by looking at the AXL refrence guide as well, but we find it easier to use SoapUI as a reference. This same process can be used to determine what to pass in to any of the Thick AXL methods.

  3. Execute the listPhone AXL method with the searchCriteria and returnedTags arguments and assign the parsed response to a variable named list_phone_response. The zeep library will take care of mapping the SOAP response to a Python dictionary by understanding the AXL Schema defined in its WSDL file. Paste the following into your file.
  4. Before running the sample script, add a few logging commands that will simply log the structured output to the console for debugging purposes.

    The first log will print the raw request payload that is sent to the CUCM while executing the service.listPhone method.

    The next log will print the raw response payload that is received from the CUCM in response to the listPhone request

    The last log will print the parsed response by zeep library. Paste the following into your file.
  5. You are now ready to run the sample Python script that will execute the axl listPhone method. Run the soap_axl.py script similarly to the way you ran the hello_world.py in the introduction to your Development Environment.

    In the VS Code navigation bar on the left, click the Run and Debug button.

    You should see a pre-configured Run and Debug Configuration for Python: soap_axl.py at the top of the column:

    Click the green start arrow next to the RUN AND DEBUG text
    As we mentioned in the introduction to your Development Environment section, normally you would need to save your files before executing them by either FileSave or Control-S. However the RUN AND DEBUG configuration will automatically save your work in progress before executing the selected file.
    Upon running the soap_axl.py Python script a new Python Debug Console terminal window will open at the bottom where the output of our script will be displayed. The screenshot below only covers the outbound SOAP payload sent to CUCM; there should be more logging output below.

    You will notice the list_phone_response variable content is significantly larger then the response SOAP payload received from CUCM. This is a function of the zeep library parsing the response against the AXL schema. As the code requested, only the name and the uuid keys will have a value assigned to them. The rest of the optional returnedTags will have a None value assigned to them. You will utilize this behavior to your advantage later when using AXL methods that require complex data structures to be passed in, such as updatePhone or addPhone for example.

Step 3 - Update a Phone with Python

Earlier you added a phone and registered it with CUCM, but the test call failed when you attempted to dial to voicemail because no Calling Search Space was configured when the phone was added. In this step you will create a request to update the existing phone and add the Calling Search Space.

  1. Make sure you still have the soap_axl.py Python file open in your VS Code editor.
  2. Inspect an example updatePhone request payload from SoapUI.

    This payload should look very similar to what you saw when you performed an addPhone with SoapUI, with the exception that nearly every parameter is now optional. Notice that you are given a choice of providing either a name or a uuid to identify the device you wish to modify. The one parameter that is present here which is not present for adding a phone is the newName parameter. This would be used if you want to rename the device. Any parameter that is not sent in the request will retain whatever setting was present for that parameter before the update call. This helps you distinguish between setting a parameter to an empty string versus keeping the existing value. For example, if you were to send <description></description> as one of the fields, this would clear the description, but if you do not send a description tag in the request at all, the description would not be modified.
  3. The parameter you want to modify to fix the calling search space is called callingSearchSpaceName which you can find just below the description. The only arguments you need to provide are the phone device name and the callingSearchSpaceName.

    Create a new variable that will supply the required arguments to the updatePhone method. The correct calling search space for your phone is Unrestricted_CSS.

  4. Execute the updatePhone AXL method with the arguments and assign the parsed response to a variable named update_phone_response. You may notice you are not passing update_phone_data directly to the updatePhone method. This method expects name and the callingSearchSpaceName as arguments. You can achieve this by unpacking the update_phone_data dictionary to its key,value pairs with the ** unpack operator.

    In other words, instead of service.updatePhone(**update_phone_data) with the name and callingSearchSpaceName specified in the update_phone_data dictionary, you could have just as well entered service.updatePhone(name='CSFPOD6UCMUSER', callingSearchSpaceName='Unrestricted_CSS'). When passing in a small number of parameters, this might be more convenient, but if you are updating a large number of parameters, the method we show below is typically easier to manage.

    For debugging purposes, log the outgoing and incoming request payloads as well as the parsed response data. Paste the following into your file.

  5. Re-run the Python: soap_axl.py by clicking the green start arrow next to the RUN AND DEBUG text

    If the end of the console output looks as following, you have successfully updated the CSFPOD6UCMUSER device's Calling Search Space.

Step 4 - Apply Phone Configuration with Python

Modifying a CUCM Phone device configuration is pretty straightforward, but if you have worked on or administered Unified CM before, you might recall that device setting changes require either a device reset or restart. Normally from Unified CM Administration you would click the Apply Config button to trigger the phone to download its latest configuration and let it decide if it needs to go through a full on reset or a quick restart depending on the configuration update. You can perform this same procedure by using the AXL API as shown below.

  1. Make sure you still have the soap_axl.py Python file open in your VS Code editor.
  2. Execute the applyPhone AXL method which only expects the name argument and assign the parsed response to a variable named apply_phone_response. For debugging purposes you will again log the outgoing and incoming request payloads as well as the parsed response data. Paste the following into your file.

  3. Re-run the Python: soap_axl.py by clicking the green start arrow next to the RUN AND DEBUG text

    If the end of the console output looks like the following, you have successfully applied your config update to the CSFPOD6UCMUSER device.

  4. Now test to see if the change of configuration worked by calling from your laptop to your pod's Voicemail pilot again 5999999.

Step 5 - Get Phone Details with Python

The next AXL method you will use is the getPhone method. You will use its response to help craft the Python arguments for the addPhone operation you will perform next, where you may recall from SoapUI could take quite large and complicated arguments. The getPhone AXL method will retrieve the full phone configuration details.

Here is a sample getPhone request that SoapUI generated. As a learning exercise, you will retrieve all the possible returnedTags. Basically, you will query for the complete phone configuration by not requesting any returnedTags.

  1. Make sure you still have the soap_axl.py Python file open in your VS Code editor.
  2. Execute the getPhone AXL method with only the name argument without supplying any returnedTags and register the response to a variable named get_phone_response. For debugging purposes we will again log the outgoing and incoming request payloads as well as the parsed response data. Paste the following into your file.

  3. Re-run the Python: soap_axl.py by clicking the green start arrow next to the RUN AND DEBUG text

    If your last console output looks like the following trimmed output, you have successfully retrieved all of your Phone device configuration for CSFPOD6UCMUSER. Both the SOAP response payload and the parsed response is quite large.

Step 6 - Add Phone with Python

The final AXL method you will execute is addPhone. You will use the previous getPhone response's parsed output to craft the variables that you will pass as arguments to addPhone method. The required parameters for the addPhone method are name, product, class, protocol, protocolSide plus any optional parameters you would like to configure.

  1. Before you create a new variable to use as an argument with the addPhone AXL method, let's recall how the first part of the get_phone_response was structured.

    If you take a closer look at the callingSearchSpaceName key, it's value is yet another dictionary with two keys _value_1 and uuid. You are not required to supply both of these keys to configure the new phone's callingSearchSpaceName. As you create a new variable named add_phone_data, you will simply set the callingSearchSpaceName key's value to the name of the calling search space which is found in the _value_1 key's value as seen above. For example:

    You will find many other parameters returned from the various "get" methods return both the name and the UUID for your convenience, but when doing an add or update, you only specify one.

  2. Make sure you still have the soap_axl.py Python file open in your VS Code editor.
  3. Create a new variable that will supply all the required arguments to the addPhone method. Paste the following into your file.
  4. Execute the addPhone AXL method which only requires the phone argument. Register the response to a variable named add_phone_response. For debugging purposes we will again log the outgoing and incoming request payloads as well as the parsed response data. Paste the following into your file.
  5. Re-run the Python: soap_axl.py by clicking the green start arrow next to the RUN AND DEBUG text

    If your last console output looks like the following output, you have successfully add a new phone.

Now that you have added a new test phone named CSFPOD6USER2, you can check that it is in actually inserted in the CUCM database.

  1. Access your CUCM server at: https://cucm1a.pod6.col.lab
  2. Login in with username admin and password C1sco.123
  3. Navigate to DevicePhone and click Find
  4. Ensure CSFPOD6USER2 is present in the device list
Now that you have explored the AXL API using Python, you can move on to exploring the Serviceability API in Python in the next section.