⬆️ ⬇️

Writing scripts for Cisco AXL

The firm in which I work for IP-telephony uses including Cisco Unified Communications Manager (CUCM). At one point, I needed to automatically monitor the status of the phones - namely, whether they are registered, whether they are in the Hunt Group, etc. A few hours of reinforced guglezh, collecting scant information in pieces, and more or less workable scripts began to appear. I will share them in this article. The version of my CUCM is 7.1.5, the IP address is assumed to be 10.0.0.10. The scripts will be in PHP, but you can easily rewrite to any other language.



First of all, you need to enable the AXL service:

1. Go to the Cisco Unified Serviceability section (top right), then go to Tools → Service Activation and enable Cisco AXL Web Service .

2. Make sure that our user has the role of Standard AXL API Access .

3. You can verify this by trying to open the https://10.0.0.10:8443/realtimeservice/services/RisPort?wsdl page. If you open a WSDL document (an XML document describing the functions provided by AXL), then everything is fine and you can go further.



getFunctions



To interact with AXL, we use the PHP language and the standard class SoapClient. Configure the client to the above URL and request a list of available functions using the standard function __getFunctions ():

$hostname = '10.0.0.10'; $client = new SoapClient("https://$hostname:8443/realtimeservice/services/RisPort?wsdl", array('trace'=>true, 'exceptions'=>true, 'location'=>"https://$hostname:8443/realtimeservice/services/RisPort", 'login'=>'LOGIN', 'password'=>'PASSWORD', )); $response = $client->__getFunctions(); print_r($response); 


We get the prototypes of the available functions:

  [0] => list(SelectCmDeviceResult $SelectCmDeviceResult, string $StateInfo) SelectCmDevice(string $StateInfo, CmSelectionCriteria $CmSelectionCriteria) [1] => list(string $StateInfo, SelectCtiItemResult $SelectCtiItemResult) SelectCtiItem(string $StateInfo, CtiSelectionCriteria $CtiSelectionCriteria) [2] => ArrayOfColumnValues ExecuteCCMSQLStatement(string $ExecuteSQLInputData, ArrayOfGetColumns $GetColumns) [3] => ArrayOfServerInfo GetServerInfo(ArrayOfHosts $Hosts) [4] => list(SelectCmDeviceResultSIP $SelectCmDeviceResultSIP, string $StateInfo) SelectCmDeviceSIP(string $StateInfo, CmSelectionCriteriaSIP $CmSelectionCriteriaSIP) 




getServerInfo



The easiest application request is server information:

 //     SOAP-   $response = $client->getServerInfo(); print_r($response); 


Result:

  [HostName] => CUCM1 [os-name] => VOS [os-version] => 2.6.9-78.ELsmp [os-arch] => i386 [java-runtime-version] => 1.6.0_24-b07 [java-vm-vendor] => Sun Microsystems Inc. [call-manager-version] => 7.1.5.33900-10 [Active_Versions] => hwdata-0.146.33.EL-11 : ... 


')

SelectCmDevice



Now let's do the actual phones. To do this, make a SOAP request. For example, we want to get information about phones 501 and 502. Pay attention to the indices of the $ items array:

 //    SOAP- $items = array(); $items['SelectItem[0]']['Item'] = "501"; $items['SelectItem[1]']['Item'] = "502"; $response = $client->SelectCmDevice("", array( "SelectBy" => "DirNumber", //    "Name",    $items   "SEPaabbccxxyyzz",  .. "Status" => "Any", "SelectItems" => $items )); $devices = $response['SelectCmDeviceResult']->CmNodes[1]->CmDevices; print_r($devices); 


Result
  [0] => stdClass Object ( [Name] => SEPAABBCC112233 [IpAddress] => 10.0.0.101 [DirNumber] => 501-Registered [Class] => Phone [Model] => 564 [Product] => 451 [BoxProduct] => 0 [Httpd] => Yes [RegistrationAttempts] => 0 [IsCtiControllable] => 1 [LoginUserId] => [Status] => Registered [StatusReason] => 0 [PerfMonObject] => 2 [DChannel] => 0 [Description] => 501 (Ivanov) [H323Trunk] => stdClass Object ( [ConfigName] => [TechPrefix] => [Zone] => [RemoteCmServer1] => [RemoteCmServer2] => [RemoteCmServer3] => [AltGkList] => [ActiveGk] => [CallSignalAddr] => [RasAddr] => ) [TimeStamp] => 1403127103 ) [1] => stdClass Object ( [Name] => SEPAABBCC112234 [IpAddress] => 10.0.0.102 [DirNumber] => 502-Registered [Class] => Phone [Model] => 30016 [Product] => 30041 [BoxProduct] => 0 [Httpd] => Yes [RegistrationAttempts] => 1 [IsCtiControllable] => 1 [LoginUserId] => [Status] => Registered [StatusReason] => 0 [PerfMonObject] => 2 [DChannel] => 0 [Description] => 502 (Petrov) [H323Trunk] => stdClass Object ( [ConfigName] => [TechPrefix] => [Zone] => [RemoteCmServer1] => [RemoteCmServer2] => [RemoteCmServer3] => [AltGkList] => [ActiveGk] => [CallSignalAddr] => [RasAddr] => ) [TimeStamp] => 1403531108 ) 




PerfmonCollectCounterData



In the following example, we will determine the state of the telephone lines - namely, whether the lines are free. If the line is busy (i.e. dialing or talking), then the value is 1. If free - then 0. To do this, access another WSDL document:

 $hostname = "10.0.0.10"; $client = new SoapClient("https://$hostname:8443/perfmonservice/services/PerfmonPort?wsdl", array('trace'=>true, 'exceptions'=>true, 'location'=>"https://$hostname:8443/perfmonservice/services/PerfmonPort", 'login'=>'LOGIN', 'password'=>'PASSWORD', )); $collection = "Cisco Lines"; $response = $client->PerfmonCollectCounterData($hostname, $collection); print_r($response); 


Result
  [0] => stdClass Object ( [Name] => \\10.0.0.10\Cisco Lines(12345678-abcd-dead-beef-0987654321ff:501)\Active [Value] => 0 [CStatus] => 1 ) [1] => stdClass Object ( [Name] => \\10.0.0.10\Cisco Lines(12345678-abcd-dead-beef-0987654321ff:502)\Active [Value] => 1 [CStatus] => 1 ) 


Here we refer to the Cisco Lines collection, but you can request data from other collections. A list of collections can be obtained using this request:

 $response = $client->PerfmonListCounter($hostname); 




ExecuteCCMSQLStatement



I was a little surprised when I learned that CUCM supports SQL queries on its internal data. In general, this is also possible. A complete list of tables can be obtained by typing the following command in the CUCM SSH console:

  admin: run sql select tabname from systables 


At a gallop across Europe, we carry out a query as to whether the phones are in the Hunt Group. Again, pay attention to the structure of the $ items array, this is rather unobvious:

 $hostname = '10.0.0.10'; $client = new SoapClient("https://$hostname:8443/realtimeservice/services/RisPort?wsdl", array('trace'=>true, 'exceptions'=>true, 'location'=>"https://$hostname:8443/realtimeservice/services/RisPort", 'login'=>'LOGIN', 'password'=>'PASSWORD', )); $items = array(); $items[] = array('Name'=>'hlog'); $items[] = array('Name'=>'description'); $response = $client->ExecuteCCMSQLStatement("SELECT h.hlog, d.description FROM device AS d INNER JOIN devicehlogdynamic AS h ON d.pkid = h.fkdevice", $items); print_r($response); 


Result
  [1] => stdClass Object ( [Name] => description [Value] => 501 (Ivanov) ) [2] => stdClass Object ( [Name] => hlog [Value] => t ) [3] => stdClass Object ( [Name] => description [Value] => 502 (Petrov) ) [4] => stdClass Object ( [Name] => hlog [Value] => f ) 


Thus, Ivanov is in the Hunt Group (in the pool of operators), but Petrov is not.



Web monitoring application



Combining all these examples, I got a fully functional web application that allows you to monitor the status of the pool of operators in real time. If you're interested, you can see the source on my github . Any suggestions and criticism are welcome.

Source: https://habr.com/ru/post/171219/



All Articles