UC Serviceability XML (SXML) with Python

The next series of CUCM APIs you will experiment with in Python are all part of a collection of APIs known as the UC Serviceability XML API that expose multiple capabilities for CUCM administrators to automate management and monitoring tasks.

For your reference, the family of UC Serviceability XML APIs consist of the following 5 APIs:

Each of these APIs has its own dedicated WSDL file that describes its unique methods (service endpoints) and unlike AXL (AXLAPI.wsdl) they are available to download directly from a given CUCM server. Note that all methods (service endpoints) are NOT available in all CUCM releases. See https://developer.cisco.com/site/sxml/documents/operations-by-release/ for more information.

Let's take a closer look at the RisPort70 and Perfmon APIs with a sample Python script.

The tasks you will accomplish in this section are:

  1. SXML RisPort client setup
  2. Query Phones with selectCmDeviceExt
  3. Query Perfmon Counters with perfmonCollectCounterData

Follow these steps to perform the above listed tasks:

Step 1 - SXML RisPort 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_sxml.py. You now have the file open for editing.

  4. Here you will find another basic Python script skeleton that you will use to execute SOAP SXML RisPort API requests again utilizing the zeep library.
  5. Start by creating a few constant variables that you will use to connect and authenticate to your Pod's CUCM SXML RisPort API.

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

  6. Unlike the AXL API, you have not downloaded the SXML WSDL files to your development workspace in order to use them. This time you will use a URL to download the WSDL file directly from your CUCM. To do this, create another constant variable for the RISPORT_WSDL_FILE. You will use this RISPORT_WSDL_FILE variable to initialize the zeep client at which time it will download the WSDL file. Each SXML api (RisPort, PerfMon, Control Center Services, etc.) has its own WSDL download URL which is documented here Paste the following highlighted line it into your file.

  7. As you did for the AXL API, you will use the session object from the requests Python library to handle authentication, certificate validation (or not), persist cookie caching across API requests, create logging configuration and utilize the zeep HistoryPlugin. Since you are already familiar with these steps, they are already pre-populated in your soap_sxml.py file.
  8. You are now ready to create the zeep.Client instance that will greatly simplify sending and receiving RisPort70 methods to/from CUCM. You will use the RISPORT_WSDL_FILE variable, session object, and the history plugin object to create the client instance. Paste the following into your file. Zeep client will authenticate and download the WSDL file.

  9. The final step before you can utilize the zeep client is to create a new ServiceProxy object named service. The RisPort WSDL file zeep client downloaded from CUCM defaults the endpoint url to https://localhost:8443/perfmonservice2/services/PerfmonService and needs to be updated to reflect your Pod's CUCM_ADDRESS. Create a new service object using the zeep.client create_service method. Again, you will utilize the CUCM_ADDRESS variable you defined earlier to set https://cucm1a.pod6.col.lab:8443/realtimeservice2/services/RISService70/ as the RisBinding endpoint url. Paste the following into your file.

Step 2 - Query Phones with selectCmDevice

The RisPort API allows you to query CUCM for the real-time state of registered devices. This is different than AXL which provides you with the static database configuration of devices. With the RisPort API you can retrieve information such as registration status, IP address, running firmware load, and more. To retrieve this data you will use the selectCmDevice method of the RisPort API as shown below.

  1. The selectCmDevice method requires the following arguments: StateInfo and CmSelectionCriteria. The selectCmDevice documentation https://developer.cisco.com/docs/sxml/#!risport70-api-reference/selectCmDevice can help identify the arguments and the data structure we need to supply to the service.selectCmDevice method. For the purposes of this sample script, you will only use the CmSelectionCriteria argument and pass a blank value for StateInfo.

    To select any device whose description begins with "Cisco", you must provide the following values as part of the CmSelectionCriteria data in the selectCmDevice request:
    • DeviceClass: Any
    • Model: 255 (Any Model)
    • Status: Any
    • NodeName: None/Blank (Any)
    • SelectBy: Description contains 'Cisco*'
    • Protocol: Any
    • DownloadStatus: Any

    The values above indicate that you want to retrieve any kind of device, any model of device (255 means any model), devices that are in any status (Registered, Unregistered, etc...), registered to any node in the cluster, registered using any protocol (SCCP or SIP), and select the devices whose description starts with the word "Cisco".

    The XML below shows what the expected SOAP request to CUCM should look like. As before, you do not have to manually create this XML body. Zeep will take care of doing this for you.

    To pass the selection criteria to the RisPort API, first create the following variable that you will use to pass as an argument to selectCmDevice method. Paste the following into your file.

  2. Now you can execute the selectCmDevice method via Python. Execute the selectCmDevice RisPort70 method with the StateInfo and CmSelectionCriteria arguments and assign the parsed response to a variable named phone_query_response. The zeep library will take care of mapping the SOAP response to a Python dictionary through its understanding of the RisPort70 WSDL file. 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. Try running the soap_sxml.py script similar to the way you ran the soap_axl.py in the previous section by following these steps:

    In 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_sxml.py at the top of the column:

    Click the green start arrow next to the RUN AND DEBUG text . Upon running the soap_sxml.py Python script a new Python Debug Console terminal window will open at the bottom where the output of the script will be displayed. The screenshot below only covers the outbound SOAP payload sent to CUCM. There should be more logging output than what is shown in the screenshot below.

    The selectCmDevice response parsed by the zeep library looks as follows. The output is quite large since you are retrieving all device details from the RIS DB. For your reference please find a trimmed output of phone_query_response below. Your console output should look slightly different but should show the CSFPOD6USER1 device in a registered state.

Step 3 - Query Perfmon Counters with perfmonCollectCounterData

In the previous step, you used the RisPort70 serviceability API to query the RIS DB for devices that matched a specific selection criteria. Next you will use the PerfMon API to query a simple set of CUCM Performance counters. If you are unfamiliar with PerfMon, it is a service available on all CUCM servers to provide real-time counters for the various services running on the server. These metrics include everything from CPU and memory utilization to number of registered devices and active calls. PerfMon has a series of objects which are logical groupings of related counters. Counters provide a single metric related to the object. For example, the Cisco CallManager object contains a variety of counters related to the Cisco CallManager service such as registered phones, active calls, and the uptime of the service. An easy way to browse the various objects and counters available is by using the Real Time Monitoring Tool (RTMT).

  1. Make sure you still have the soap_sxml.py Python file open in your VS Code editor.
  2. First, initialize a new zeep client for the PerfMon API using its WSDL file. Like the RisPort API, you will download it directly from the CUCM server when initializing the zeep client. You will reuse the session object you created for the RisPort and the logging settings, but will create a new zeep client for the PerfMon Api. Paste the following highlighted lines it into your file.

  3. Here is a sample perfmonCollectCounterData request payload that you will craft in Python that queries all the counters in the "Cisco CallManager" perfmon object:

    The perfmonCollectCounterData method requires the following arguments: Host and Object. The perfmonCollectCounterData documentation https://developer.cisco.com/docs/sxml/#!perfmon-api-reference/perfmoncollectcounterdata can help identify the arguments and the data structure you must provide to the service.perfmonCollectCounterData method.

  4. Execute the perfmonCollectCounterData method while passing Host="cucm1a.pod6.col.lab" and Object="Cisco CallManager". Register the response to a variable named perfmon_query_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.

  5. Try running the soap_sxml.py script again.

    In 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_sxml.py at the top of the column:

    Click the green start arrow next to the RUN AND DEBUG text . Upon running the soap_sxml.py Python script a new Python Debug Console terminal window will open at the bottom where the output of the script will be displayed. The screenshot below only covers the outbound SOAP payload sent to CUCM for the perfmonCollectCounterData request, there should be a lot more logging output than what is shown in the screenshot below.

    The perfmon_query_response response parsed by the zeep library should look similar to the output below. The output is quite large since you are retrieving all PerfMon Counters for the "Cisco CallManager" class. For your reference please find a trimmed output of perfmon_query_response.

The method of using the PerfMon API highlighted above is the simplest use of the API. Most use cases involve continuously querying the same performance counters at a certain time interval and storing them, perhaps as a time-series in a database of some kind. To do this, the PerfMon API provides a mechanism by which you open a session, add counters to that session, then periodically collect session data for those counters. For more information on the more advanced usage, reference the PerfMon API Reference and look at how to use the perfMonOpenSession, perfMonAddCounter, and perfMonCollectSessionData methods.

You have now completed both the AXL and Serviceability XML APIs examples with Python. In the next section you will be introduced to REST-based APIs.