Asterisk is primarily designed to run on a single system. However, as requirements for scalability increase, it is common for deployments to require multiple Asterisk servers. Since that has become increasingly common, some features have been added to make it easier to coordinate multiple Asterisk servers. One of those features is distributed device state support.
What this means is that if a device is on a call on one Asterisk server, the state of that device on all servers reflects that. To be more specific, the way this works is that every server knows the state of each device from the perspective of each server. Using this collection of states, each server will calculate what the overall device state value is to report to the rest of Asterisk.
To accomplish distributed device state, some sort of messaging mechanism must be used for the servers to communicate with each other. Two such mechanisms are supported as of Asterisk 1.8: AIS and XMPP.
The Application Interface Specification (AIS) is a standardized set of messaging middleware APIs. The definition for the APIs is provided by the Service Availability Forum. The open source implementation of AIS that was used for the development and testing of this functionality is OpenAIS, which is built on Corosync.
Corosync, and thus OpenAIS, is built in such a way that nodes must be located on the same high-speed, low-latency LAN. If your deployment is geographically distributed, you should use the XMPP-based distributed device state support, which is discussed in the section called “Using XMPP”.
The first step to getting the necessary components installed is to install Corosync and OpenAIS. Corosync depends on the NSS library. Install the libnss3-dev package on Ubuntu or the nss-devel package on CentOS.
Next, install Corosync and OpenAIS. There may be packages available, but they are also fairly straightforward to install from source. Download the latest releases from the Corosync and OpenAIS home pages. Then, execute the following commands to compile and install each package:
$tar xvzf corosync-1.2.8.tar.gz$cd corosync-1.2.8$./configure$make$sudo make install$tar xvzf openais-1.1.4.tar.gz$cd openais-1.1.4$./configure$make$sudo make install
If you installed Asterisk prior to installing Corosync and OpenAIS, you will need to re-compile and reinstall Asterisk to get AIS support. Start by running the Asterisk configure script. The configure script is responsible for inspecting the system to find out which optional dependencies can be found so that the build system knows which modules can be built:
$cd /path/to/asterisk$./configure
After running the
        configure script, run the
        menuselect tool to ensure that
        Asterisk has been told to build the
        res_ais module (this module can be found in the
        Resource Modules section of
        menuselect):
$make menuselect
Finally, compile and install Asterisk:
$make$sudo make install
This is a pretty quick and crude set of instructions for compiling and installing Asterisk. For a much more complete set of instructions, please see Chapter 3, Installing Asterisk.
Now that OpenAIS has been installed, it needs to be
        configured. There is a configuration file for both OpenAIS and
        Corosync that must be put in place. Check to see if
        /etc/ais/openais.conf and
        /etc/corosync/corosync.conf exist. If they do not
        exist, copy in the sample configuration files:
$sudo mkdir -p /etc/ais$cd openais-1.1.4$sudo cp conf/openais.conf.sample /etc/ais/openais.conf$sudo mkdir -p /etc/corosync$cd corosync-1.2.8$sudo cp conf/corosync.conf.sample /etc/corosync/corosync.conf
Next, you will need to edit both
        the openais.conf and
        corosync.conf files. There are a number of
        options here, but the most important one that must be changed is the
        bindnetaddr option in the
        totem-interface section. This must be set to the IP
        address of the network interface that this node will use to
        communicate with the rest of the cluster:
totem {
    ...
    interface {
        ringnumber: 0
        bindnetaddr: 10.24.22.144
        mcastaddr: 226.94.1.1
        mcastport: 5405
    }
}For detailed documentation on the rest of the options in these configuration files, see the associated manpages:
$man openais.conf$man corosync.conf
To get started with testing out basic OpenAIS connectivity, try starting the aisexec application in the foreground and watching the output:
$sudo aisexec -f
For example, if you watch the output of aisexec on the first node while you bring up the second node, you should see output that reflects that the cluster now has two connected nodes:
Nov 13 06:55:30 corosync [CLM ] CLM CONFIGURATION CHANGE Nov 13 06:55:30 corosync [CLM ] New Configuration: Nov 13 06:55:30 corosync [CLM ] r(0) ip(10.24.22.144) Nov 13 06:55:30 corosync [CLM ] r(0) ip(10.24.22.242) Nov 13 06:55:30 corosync [CLM ] Members Left: Nov 13 06:55:30 corosync [CLM ] Members Joined: Nov 13 06:55:30 corosync [CLM ] r(0) ip(10.24.22.242) Nov 13 06:55:30 corosync [TOTEM ] A processor joined or left the membership and a new membership was formed. Nov 13 06:55:30 corosync [MAIN ] Completed service synchronization, ready to provide service.
The res_ais module for
        Asterisk has a single configuration file,
        /etc/asterisk/ais.conf. One short section is
        required in this file to enable distributed device state in an AIS
        cluster. Place the following contents in the
        /etc/asterisk/ais.conf file:
[device_state] type = event_channel publish_event = device_state subscribe_event = device_state
There is an Asterisk CLI command that can be used to ensure that this configuration has been loaded properly:
*CLI>ais evt show event channels============================================================= === Event Channels ========================================== ============================================================= === === --------------------------------------------------------- === Event Channel Name: device_state === ==> Publishing Event Type: device_state === ==> Subscribing to Event Type: device_state === --------------------------------------------------------- === =============================================================
Another useful
        Asterisk CLI command provided by the
        res_ais module is used to list the members of the
        AIS cluster:
*CLI>ais clm show members============================================================= === Cluster Members ========================================= ============================================================= === === --------------------------------------------------------- === Node Name: 10.24.22.144 === ==> ID: 0x9016180a === ==> Address: 10.24.22.144 === ==> Member: Yes === --------------------------------------------------------- === === --------------------------------------------------------- === Node Name: 10.24.22.242 === ==> ID: 0xf216180a === ==> Address: 10.24.22.242 === ==> Member: Yes === --------------------------------------------------------- === =============================================================
Now that you’ve set up and configured distributed device
        state using OpenAIS, there are some simple tests that can be done
        using custom device states to ensure that device states are being
        communicated between the servers. Start by creating a test hint in the
        Asterisk dialplan,
        /etc/asterisk/extensions.conf:
[devstate_test] exten => foo,hint,Custom:abc
Now, you can adjust the custom device state from the Asterisk CLI using the dialplan set global CLI command and then check the state on each server using the core show hints command. For example, we can use this command to set the state on one server:
pbx1*CLI>dialplan set global DEVICE_STATE(Custom:abc) INUSE-- Global variable 'DEVICE_STATE(Custom:abc)' set to 'INUSE'
and then, check the state on another server using this command:
*CLI>core show hints-= Registered Asterisk Dial Plan Hints =- foo@devstatetest : Custom:abc State:InUse Watchers 0
If you would like to dive deeper
        into the processing of distributed device state changes, there are
        some useful debug messages that can be enabled. First, enable debug on
        the Asterisk console in
        /etc/asterisk/logger.conf. Then, enable debugging
        at the Asterisk CLI:
*CLI>core set debug 1
With the debug output enabled, you will see some messages that show how Asterisk is processing each state change. When the state of a device changes on one server, Asterisk checks the state information it has for that device on all servers and determines the overall device state. The following examples illustrate:
*CLI>dialplan set global DEVICE_STATE(Custom:abc) NOT_INUSE-- Global variable 'DEVICE_STATE(Custom:abc)' set to 'NOT_INUSE' [Nov 13 13:27:12] DEBUG[14801]: devicestate.c:652 handle_devstate_change: Processing device state change for 'Custom:abc' [Nov 13 13:27:12] DEBUG[14801]: devicestate.c:602 process_collection: Adding per-server state of 'Not in use' for 'Custom:abc' [Nov 13 13:27:12] DEBUG[14801]: devicestate.c:602 process_collection: Adding per-server state of 'Not in use' for 'Custom:abc' [Nov 13 13:27:12] DEBUG[14801]: devicestate.c:609 process_collection: Aggregate devstate result is 'Not in use' for 'Custom:abc' [Nov 13 13:27:12] DEBUG[14801]: devicestate.c:631 process_collection: Aggregate state for device 'Custom:abc' has changed to 'Not in use'*CLI>dialplan set global DEVICE_STATE(Custom:abc) INUSE-- Global variable 'DEVICE_STATE(Custom:abc)' set to 'INUSE' [Nov 13 13:29:30] DEBUG[14801]: devicestate.c:652 handle_devstate_change: Processing device state change for 'Custom:abc' [Nov 13 13:29:30] DEBUG[14801]: devicestate.c:602 process_collection: Adding per-server state of 'Not in use' for 'Custom:abc' [Nov 13 13:29:30] DEBUG[14801]: devicestate.c:602 process_collection: Adding per-server state of 'In use' for 'Custom:abc' [Nov 13 13:29:30] DEBUG[14801]: devicestate.c:609 process_collection: Aggregate devstate result is 'In use' for 'Custom:abc' [Nov 13 13:29:30] DEBUG[14801]: devicestate.c:631 process_collection: Aggregate state for device 'Custom:abc' has changed to 'In use'
The eXtensible Messaging and Presence Protocol (XMPP), formerly (and still commonly) known as Jabber, is an IETF standardized communications protocol. It is most commonly known as an IM protocol, but it can be used for a number of other interesting applications as well. The XMPP Standards Foundation (XSF) works to standardize extensions to the XMPP protocol. One such extension, referred to as PubSub, provides a publish/subscribe mechanism.
Asterisk has the ability to use XMPP PubSub to distribute device state information. One of the nice things about using XMPP to accomplish this is that it works very well for geographically distributed Asterisk servers.
To distribute device states using XMPP, you will need an XMPP server that supports PubSub. One such server that has been successfully tested against Asterisk is Tigase.
The Tigase website has instructions for installing and configuring the Tigase server. We suggest that you follow those instructions (or the instructions provided for whatever other server you may choose to use) and come back to this book when you’re ready to work on the Asterisk-specific parts.
On the Asterisk side of things, you
        will need to ensure that you have installed the
        res_jabber module. You can check to see if it is
        already loaded at the Asterisk CLI:
*CLI>module show like jabberModule Description Use Count res_jabber.so AJI - Asterisk Jabber Interface 0 1 modules loaded
If you are using a custom
        /etc/asterisk/modules.conf file that lists only
        specific modules to be loaded, you can also check the filesystem to
        see if the module was compiled and installed:
$ls -l /usr/lib/asterisk/modules/res_jabber.so-rwxr-xr-x 1 root root 837436 2010-11-12 15:33 /usr/lib/asterisk/modules/res_jabber.so
If you do not yet have
        res_jabber installed, you will need to install the
        iksemel and
        OpenSSL libraries. Then, you will need to
        recompile and reinstall Asterisk. Start by
        running the Asterisk
        configure script, which is responsible for
        inspecting the system and locating optional dependencies, so that the
        build system knows which modules can be built:
$cd /path/to/asterisk$./configure
After running the
        configure script, run the
        menuselect tool to ensure that
        Asterisk has been told to build the
        res_jabber module. This module can be found in the
        Resource Modules section of
        menuselect:
$make menuselect
Finally, compile and install Asterisk:
$make$sudo make install
This is a pretty quick and crude set of instructions for compiling and installing Asterisk. For a much more complete set of instructions, please see Chapter 3, Installing Asterisk.
Unfortunately, Asterisk is currently not able to register new accounts on an XMPP server. You will have to create an account for each server via some other mechanism. The method we used while testing was to use an XMPP client such as Pidgin to complete the account registration process. After account registration is complete, the XMPP client is no longer needed. For the rest of the examples, we will use the following two buddies, both of which are on the server jabber.shifteight.org:
The /etc/asterisk/jabber.conf file
        will need to be configured on each server. We will show the
        configuration for a two-server setup here, but the configuration can
        easily be expanded to more servers as needed. Example 14.2, “jabber.conf for server1” shows the contents of the
        configuration file for server 1 and Example 14.3, “jabber.conf for server2” shows the contents of the
        configuration file for server 2. For additional information on the
        jabber.conf options associated with distributed
        device states, see the configs/jabber.conf.sample
        file that is included in the Asterisk source tree.
Example 14.2. jabber.conf for server1
[general] autoregister = yes [asterisk] type = client serverhost = jabber.shifteight.org pubsub_node = pubsub.jabber.shifteight.org username = server1@jabber.shifteight.org/astvoip1 secret = mypassword distribute_events = yes status = available usetls = no usesasl = yes buddy = server2@jabber.shifteight.org/astvoip2
Example 14.3. jabber.conf for server2
[general] autoregister = yes [asterisk] type = client serverhost = jabber.shifteight.org pubsub_node = pubsub.jabber.shifteight.org username = server2@jabber.shifteight.org/astvoip2 secret = mypassword distribute_events = yes status = available usetls = no usesasl = yes buddy = server1@jabber.shifteight.org/astvoip1
To ensure that everything is working properly, start by
        doing some verification of the jabber.conf
        settings on each server. There are a couple of relevant
        Asterisk CLI commands that can be used
        here. The first is the jabber show connected
        command, which will verify that Asterisk has successfully logged
        in with an account on the jabber server. The
        output of this command on the first server shows:
*CLI>jabber show connectedJabber Users and their status: User: server1@jabber.shifteight.org/astvoip1 - Connected ---- Number of users: 1
Meanwhile, if jabber show connected is executed on the second server, it shows:
*CLI>jabber show connectedJabber Users and their status: User: server2@jabber.shifteight.org/astvoip2 - Connected ---- Number of users: 1
The next useful command for verifying the setup is jabber show buddies. This command allows you to verify that the other server is correctly listed on your buddy list. It also lets you see if the other server is seen as currently connected. If you were to run this command on the first server without Asterisk currently running on the second server, the output would look like this:
*CLI>jabber show buddiesJabber buddy lists Client: server1@jabber.shifteight.org/astvoip1 Buddy: server2@jabber.shifteight.org Resource: None Buddy: server2@jabber.shifteight.org/astvoip2 Resource: None
Next, start Asterisk on the second server and run jabber show buddies on that server. The output will contain more information, since the second server will see the first server online:
*CLI>jabber show buddiesJabber buddy lists Client: server2@jabber.shifteight.org/astvoip2 Buddy: server1@jabber.shifteight.org Resource: astvoip1 node: http://www.asterisk.org/xmpp/client/caps version: asterisk-xmpp Jingle capable: yes Status: 1 Priority: 0 Buddy: server1@jabber.shifteight.org/astvoip1 Resource: None
At this point, you should be ready to test out the distribution of device states. The procedure is the same as that for testing device states over AIS, which can be found in the section called “Testing device state changes”.