You may already be familiar with Asterisk, the widely-deployed open-source telephony framework. If you aren't, you should check it out. It's a pretty cool piece of software. A low-load instance of Asterisk can be deployed to use the filesystem to store things like phone-registration data and voicemails. But if you want to do anything fancy with Asterisk, or if you happen to care about things like fault-tolerance, you might look at pointing Asterisk at a database. And if you happen to have a large Asterisk cluster built to handle significant load, you might look at pointing Asterisk at an elastically-scalable database. In this post, I'll walk you through setting up a minimal Asterisk installation on a single RPM-based Linux machine with NuoDB. You can go much farther with Asterisk installs spanning several data centers, but I'll leave those headaches to the experts. Pairing such an installation with NuoDB will at least take the database pain out of such a setup. Let's dive in.
First, download and install NuoDB.
This will start a NuoDB broker on this host. Next, we start a Transaction Engine and Storage Manager:
java -jar /opt/nuodb/jar/nuodbmanager.jar --broker localhost --user domain --password bird --command "start process te database asteriskCDR host localhost options '--dba-user asteriskUser --dba-password mySecret'"
Setting up ODBC
While there is native support in Asterisk to talk directly to MySQL and PostgreSQL, the more tested and hardened path is to connect to a database through ODBC. Here, we install unixODBC, the ODBC driver manager implementation for Unix-like operating systems.
yum install gcc gcc-c++ ncurses-devel unixODBC unixODBC-devel
This created two files: /etc/odbc.ini and /etc/odbcinst.ini which we now edit to point at our NuoDB instance.
Description = NuoDB ODBC3 Driver DSN
Driver = /opt/nuodb/lib64/libNuoODBC.so
Database = asteriskCDR
ServerName = localhost
User = asteriskUser
Password = mySecret
Schema = user
We can leave /etc/odbcinst.ini empty, or if you would like to enable (a very verbose!) logging:
TraceFile = /tmp/odbc.log
Trace = Yes
These are by no means the only options to get unixODBC up and running, but we'll roll with this for now. Let's make sure that what we've got so far works:
| Connected! |
| sql-statement |
| help [tablename] |
| quit |
At the time of writing, the current tested and stable release of Asterisk is 11.4.0, but you can check here for the release of your choice.
yum install libtool-ltdl libtool-ltdl-devel sqlite-devel libxml2-devel openssl-devel libuuid-devel
sha1sum -c asterisk-11.4.0.tar.gz.sha1
tar zxvf asterisk-11.4.0.tar.gz
./configure --libdir=/usr/lib64 --disable-xmldoc
make menuselect && make && make install && make samples && make config
During make menuselect, check the Call Detail Recording (CDR) to make sure that cdr_odbc is enabled. Press q to leave make menuselect. After that, you can get yourself a coffee and spend a few minutes checking out Dinosaur Comics.
If compilation on your system succeeded and your distribution is recognized by the make install phase, you should be able to start the Asterisk service:
Connecting Asterisk and NuoDB
Asterisk can utilize a database in various ways. As an example, we'll set up CDR logging.
enabled => yes
dsn => NuoODBC
username => asteriskUser
password => mySecret
pre-connect => yes
sanitysql => select 1 from dual
We force the reload of the configuration files:
Now we can check the database connection with a simple command inside the Asterisk console.
p131*CLI> odbc show
ODBC DSN Settings
Last connection attempt: 2013-09-03 10:45:41
As you might have guessed, we'll be logging Call Detail Records into a table called cdr. Let's create the table:
CREATE SEQUENCE "SEQ_cdr_cdrID" START WITH 1;
CREATE TABLE "cdr" ("cdrID" REAL GENERATED BY DEFAULT AS IDENTITY("SEQ_cdr_cdrID") NOT NULL, "calldate" TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', "clid" VARCHAR(80) NOT NULL DEFAULT '', "src" VARCHAR(80) NOT NULL DEFAULT '', "dst" VARCHAR(80) NOT NULL DEFAULT '', "dcontext" VARCHAR(80) NOT NULL DEFAULT '', "channel" VARCHAR(80) NOT NULL DEFAULT '', "dstchannel" VARCHAR(80) NOT NULL DEFAULT '', "lastapp" VARCHAR(80) NOT NULL DEFAULT '', "lastdata" VARCHAR(80) NOT NULL DEFAULT '', "duration" INTEGER NOT NULL DEFAULT '0', "billsec" INTEGER NOT NULL DEFAULT '0', "disposition" VARCHAR(45) NOT NULL DEFAULT '', "amaflags" INTEGER NOT NULL DEFAULT '0', "accountcode" VARCHAR(20) NOT NULL DEFAULT '', PRIMARY KEY ("cdrID"));
CREATE INDEX "IDX_cdr_calldate" ON "cdr" ("calldate");
CREATE INDEX "IDX_cdr_dst" ON "cdr" ("dst");
CREATE INDEX "IDX_cdr_accountcode" ON "cdr" ("accountcode");
A Simple Test
To show that this all works, we'll add a few lines of Dialplan to the bottom of /etc/asterisk/extensions.conf and test the setup with SIPp.
exten => 123,1,Answer
exten => 123,2,SetMusicOnHold(default)
exten => 123,3,WaitMusicOnHold(2)
exten => 123,4,Hangup
We force the reload of the configuration files again, and install SIPp:
service asterisk restart
yum install sipp
If your distribution's repositories don't contain SIPp, it's only a simple make away. To test our installation, we run the following command. You can verify that SIPp is pointed at your Asterisk instance by seeing the logs in the Asterisk console.
Now we can confirm that we got call logs by seeing a non-zero number after issuing:
Since Asterisk is a framework that can run a wide variety of telephony applications, there are arbitrarily-many possible connection points between it and a database. We've tested the CDR functionality, and a few other paths, but we'd love your feedback. Please let us know about your experiences using Asterisk and NuoDB!