This page is about using Cisco Callmanagers - they are now calling it Unified Communications Manager - database API: "AVVID XML Layer" or "Administrativ XML Layer" or "Administration XML" (AXL).

I try to present this page in English, because there is nearly no information about AXL in the web. If you find faults, please don't hesitate to tell me.

 

Preface

I am experienced in using AXL productivly since more than 5 years (Oct 2010) for a big installation (more than 30,000 phones). AXL is very hard work with a lot of trial and error, because there is nearly no documentation from Cisco, but a lot of bugs. You will find some weblinks in the Link section.

Because a lot of Cisco information 'is in the web' (;- ) it is useful, if you have a CCO account: Just register (external link), it's free.

What is AXL good for?

AXL is an abstraction layer for the Cisco Unified Communications Manager (I will call it CUCM) configuration database. It is a webservice, theoretically you just have to consume the WSDL file and write an AXL client, which calls the generated AXL methods.

If you want to add 20 Calling Search Spaces to a CUCM you can do this manually, via BAT or you can use AXL: addCSS-Method. To get a rough idea what you can do with AXL, have look at hundreds of commands: AXL API Reference (external link). Nearly everything you can do with the ccmadmin webpages you can also do with AXL, even addCallmanager or updateServiceParameter.

With AXL you can decrease the TCO, because nearly everything could happen automatically, without interaction. The second advantage is, that there are much less faulty configuations in your system. But normally you don't try to do everything with AXL, but that part of your work, which consumes a lot of time but is stupid work for example to change Pickup Groups or reset a password or PIN.

OK, after knowing what we can do with AXL the big question is: How?

How use AXL?

AXL is nothing else than SOAP (external link), means Simple Object Access Protocol, but isn't simple at all. Because we are talking about webtechnology, you need HTTP/HTTPS access to the CUCM. Cisco is using HTTPS since CUCM 5.x, for Unified Callmanager 4.x you use HTTP. I assume, this is no problem, because you need HTTPS for accessing the ccmadmin pages.

SOAP is an XML technique, so you need a possibility to form XML into HTTPS packets and do an authentication. Normally you will have to choose a scripting language (like Perl, PHP, Phyton...) or programming language (Java, C++, C#). You are free to choose anyone, you like if it supports SOAP. For example the TU Chemnitz uses Phyton: Info (external link), we used PHP in the beginning and moved to Java and C#.

Although I am not a (good) programmer I will do all examples etc. with Java. Everything you need to program with Java is free of charge and Cisco itself uses obviously Java for the server part of AXL - they are using Tomcat ...

You know, that you need a Java JDK, may be Eclipse or something as an IDE. The next question is: How can I use Java for AXL?

Using Java for AXL

There are some possibilities to use AXL:

The last posibility is the >>best paractise<< but not easy at all. So I will describe the first possibility and may be the third one.

AXL from the scratch

Using this possibility you follow the Java example in the CUCM AXL API documentation, which does a getPhone as an example:

First do the import stuff:

import java.io.*; import java.net.*;
import javax.net.ssl.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

now the AXLClient starts:

public class AXLJavaClient { public static void main(String[] args) {
byte[] bArray = null; // buffer for reading response from
Socket socket = null; // socket to AXL server
OutputStream out = null; // output stream to server
InputStream in = null; // input stream from server
String sAXLSOAPRequest = "";
// HTTPS header and SOAP payload
String sAXLRequest = null; // will hold only the SOAP payload

First thing to do: Authentication. You need to base64 encode username and password for the AXL user. Who? You need to create a usergroup (with ccmadmin) which has the AXL role, then an application user which is member of this AXL group. Let's say you create axluser with password axlsecret. You need to encode this string: axluser:axlsecret, which you be YXhsdXNlcjpheGxzZWNyZXQ= (try youself at Online Encoder (external link)).


String authorization = "axluser" + ":" + "axlsecret";
authorization = new sun.misc.BASE64Encoder().encode(authorization.getBytes());

Next is to generate the HTTP packet, the SOAPAction contains a version parameter.

// Form the http header
sAXLSOAPRequest = "POST /axl/ HTTP/1.0\r\n";
sAXLSOAPRequest += "Host:cucmserver:8443\r\n";
sAXLSOAPRequest += "Authorization: Basic " + authorization + "\r\n";
sAXLSOAPRequest += "Accept: text/*\r\n";
sAXLSOAPRequest += "Content-type: text/xml\r\n";
sAXLSOAPRequest += "SOAPAction: \"CUCM:DB ver=6.0\"\r\n";
sAXLSOAPRequest += "Content-length: ";

Next step is to build the SOAP Payload including the getPhone method. By the way, I didn't found any use of the sequence, you are not able to send a bundle of requests.

// Build the SOAP payload
sAXLRequest = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" ";
sAXLRequest += "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">";
sAXLRequest += "<SOAP-ENV:Body> <axl:getPhone xmlns:axl=\"http://www.cisco.com/AXL/1.0\" ";
sAXLRequest += " xsi:schemaLocation=\"http://www.cisco.com/AXL/1.0 http://ccmserver/schema/axlsoap.xsd\" ";
sAXLRequest += "sequence=\"1234\"> <phoneName>SEP000000000009</phoneName>";
sAXLRequest += "</axl:getPhone> </SOAP-ENV:Body> </SOAP-ENV:Envelope>";

Now we have to finish the HTTP(S) header by adding the content length to it:

// finish the HTTPS Header
sAXLSOAPRequest += sAXLRequest.length();
sAXLSOAPRequest += "\r\n\r\n";

Next step: We add the SOAP paylod tho the http packet:

// now add the SOAP payload to the HTTPS header, which completes the AXL
// SOAP request
sAXLSOAPRequest += sAXLRequest;

OK, now we start and do some SSL stuff:

try {
AXLJavaClient axl = new AXLJavaClient();
// Implement the certificate-related stuffs required for sending request via https
X509TrustManager xtm = axl.new MyTrustManager();
TrustManager[] mytm = { xtm };
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(null, mytm, null);
SSLSocketFactory sslFact = (SSLSocketFactory) ctx.getSocketFactory();

Here starts the HTTPS socket to 192.168.1.100 and TCP port 8443:

socket = (SSLSocket) sslFact.createSocket("192.168.1.100", Integer.parseInt("8443"));
in = socket.getInputStream();
// send the request to the server
// read the response from the server
StringBuffer sb = new StringBuffer(2048);
bArray = new byte[2048];
int ch = 0;
int sum = 0;
out = socket.getOutputStream();
out.write(sAXLSOAPRequest.getBytes());

After sending the request to CUCM, we try to read the answer:

while ((ch = in.read(bArray)) != -1) {
sum += ch;
sb.append(new String(bArray, 0, ch));
}
socket.close();
// output the response to the standard output
System.out.println(sb.toString());
} catch (UnknownHostException e) {
System.err.println("Error connecting to host: " + e.getMessage());
return;
} catch (IOException ioe) {
System.err.println("Error sending/receiving from server: " + ioe.getMessage());
// close the socket
} catch (Exception ea) {
System.err.println("Unknown exception " + ea.getMessage());
return;
}
finally{
try {
if (socket != null)
socket.close();
} catch (Exception exc) {
exc.printStackTrace();
System.err.println("Error closing connection to server: "+ exc.getMessage());
}
}
}

That was it.

Down here you will find the SSL-Trustmanager, which will load the SSL certificate to the truststore for this Java program:

public class MyTrustManager implements X509TrustManager {
MyTrustManager() {
// create/load keystore
}
public void checkClientTrusted(X509Certificate chain[], String authType)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate chain[], String authType)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
}

AXL using WSDL generated classes

- later -

Links