Enterprise Deployment with Corosync
About
This is uses the same concept discussed here, which I also wrote.
This setup was tested on Debian Squeeze. There are two example servers here, fs01-a (10.10.10.8) and fs01-b (10.10.10.9).
10.10.10.11 will be the floating IP used here. This tutorial assumes you have ODBC setup so both nodes can connect to the same database. Please note that 10.10.10.11 should be a public facing IP, it is only used as an example here.
Network Configuration
Add each node to hosts file
root@fs01-a:~# echo "10.10.10.8 fs01-a" >> /etc/hosts
root@fs01-a:~# echo "10.10.10.9 fs01-b" >> /etc/hosts
root@fs01-b:~# echo "10.10.10.8 fs01-a" >> /etc/hosts
root@fs01-b:~# echo "10.10.10.9 fs01-b" >> /etc/hosts
Create SSH keys
root@fs01-a:~# ssh-keygen -t dsa -f ~/.ssh/id_dsa -N ""
root@fs01-b:~# ssh-keygen -t dsa -f ~/.ssh/id_dsa -N ""
Create SSH key to other server
root@fs01-a:~# scp -P 22 .ssh/id_dsa.pub root@fs01-b:/root/
root@fs01-a:~# cat id_dsa.pub >> .ssh/authorized_keys
root@fs01-a:~# rm -rf fs01-b.pub
root@fs01-b:~# scp -P 22 .ssh/id_dsa.pub root@fs01-a:/root/
root@fs01-b:~# cat id_dsa.pub >> .ssh/authorized_keys
root@fs01-b:~# rm -rf fs01-a.pub
Allow FreeSWITCH to bind to nonlocal IP
Add the following line to /etc/sysctl.conf
echo 'net.ipv4.ip_nonlocal_bind=1' >> /etc/sysctl.conf
Restart networking:
/etc/init.d/networking restart
Run:
sysctl -p
You should see:
net.ipv4.ip_nonlocal_bind = 1
If you don't, you did something wrong, if you do, continue...
Corosync/Pacemaker
Install Corosync & Pacemaker
apt-get install pacemaker crmsh -y
corosync is included as a dependency of pacemaker
Configure Corosync
root@fs01-a:~# export ais_port=4000
root@fs01-a:~# export ais_mcast=226.94.1.1
root@fs01-a:~# export ais_addr=`ip addr | grep "inet " | tail -n 1 | awk '{print $4}' | sed s/255/0/`
root@fs01-a:~# cp /etc/corosync/corosync.conf.example /etc/corosync/corosync.conf
root@fs01-a:~# sed -i.bak "s/.*mcastaddr:.*/mcastaddr:\ $ais_mcast/g" /etc/corosync/corosync.conf
root@fs01-a:~# sed -i.bak "s/.*mcastport:.*/mcastport:\ $ais_port/g" /etc/corosync/corosync.conf
root@fs01-a:~# sed -i.bak "s/.*\tbindnetaddr:.*/bindnetaddr:\ $ais_addr/g" /etc/corosync/corosync.conf
root@fs01-a:~# cat >> /etc/corosync/corosync.conf <<EOT
aisexec {
user: root
group: root
}
service {
name: pacemaker
ver: 0
}
EOT
root@fs01-a:~# corosync-keygen
root@fs01-a:~# scp -P 22 /etc/corosync/authkey root@fs01-b:/etc/corosync/authkey
root@fs01-a:~# scp -P 22 /etc/corosync/corosync.conf root@fs01-b:/etc/corosync/corosync.conf
root@fs01-a:~# sed -i "s/no/yes/g" /etc/default/corosync
root@fs01-b:~# sed -i "s/no/yes/g" /etc/default/corosync
OpenAIS is deprecated in favor of corosync.
https://github.com/corosync/openais
The LSB (Linux Standards Base) Script
Copy and paste this script into /etc/init.d/FSSofia on both nodes.
#!/bin/sh
### -*- mode:shell-script; indent-tabs-mode:nil; sh-basic-offset:2 -*-
### BEGIN INIT INFO
# Provides: FSSofia
# Required-Start: $network $remote_fs $local_fs
# Required-Stop: $network $remote_fs $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: FSSofia
# Description: FSSofia Status
### END INIT INFO
#set -x
FS_CLI_PROG='/usr/local/freeswitch/bin/fs_cli'
FS_CLI_HOST='127.0.0.1'
FS_CLI_PORT='8021'
FS_CLI_PASS='ClueCon'
PROFILES='internal'
usage() {
echo "Usage: $0 profile1[,profile2[,etc]] {start|stop|status}"
exit 1
}
fs_cli() {
$FS_CLI_PROG -H $FS_CLI_HOST -P $FS_CLI_PORT -p $FS_CLI_PASS -x "$1"
}
sofia_profile_started() {
fs_cli "sofia xmlstatus" | grep "<name>$1</name>" | wc -l
}
if [ $# != 1 ]; then
usage
fi
#PROFILES=`echo $1 | tr ',' ' '`
CMD=$1
#was $2
case "$CMD" in
'start')
fs_cli "sofia recover"
exit 0
;;
'stop')
exit 0
;;
'status')
for p in $PROFILES; do
if [ `sofia_profile_started "$p"` -eq 0 ]; then
echo "$p DOWN"
exit 3
fi
done
echo "OK"
exit 0
;;
*)
usage
;;
esac
Make the script executable
root@fs01-a:~# chmod +x /etc/init.d/FSSofia
root@fs01-b:~# chmod +x /etc/init.d/FSSofia
Restart Corosync
root@fs01-a:~# /etc/init.d/corosync restart
root@fs01-b:~# /etc/init.d/corosync restart
crm configure show
Configure corosync/pacemaker as follows
root@fs01-a:~# crm configure edit
node fs01-a \
attributes standby="off"
node fs01-b \
attributes standby="off"
primitive fs lsb:FSSofia \
op monitor interval="1s" enabled="true" timeout="2s" on-fail="standby" \
meta target-role="Started"
primitive fs-ip ocf:heartbeat:IPaddr2 \
params ip="10.10.10.11" nic="eth0:0" cidr_netmask="24" \
op monitor interval="10s"
group cluster_services fs-ip fs
location cli-prefer-cluster_services cluster_services \
rule $id="cli-prefer-rule-cluster_services" inf: #uname eq fs01-a
property $id="cib-bootstrap-options" \
dc-version="1.0.9-74392a28b7f31d7ddc86689598bd23114f58978b" \
cluster-infrastructure="openais" \
expected-quorum-votes="2" \
stonith-enabled="false" \
last-lrm-refresh="1348755080" \
no-quorum-policy="ignore"
rsc_defaults $id="rsc-options" \
resource-stickiness="100"
Configure FreeSWITCH
Set FreeSWITCH to listen on the floating IP and configure ODBC.
sofia.conf.xml
You should have the following parameters set in sofia.conf.xml on both nodes. The Database needs to be shared between the two+ nodes. Please see the databases wiki for the proper odbc connection string.
<param name="odbc-dsn" value="database:username:password"/>
<param name="track-calls" value="true"/>
<param name="rtp-ip" value="10.10.10.11"/>
<param name="sip-ip" value="10.10.10.11"/>
<param name="presence-hosts" value="10.10.10.11"/>
<param name="ext-rtp-ip" value="10.10.10.11"/>
<param name="ext-sip-ip" value="10.10.10.11"/>
Configure sip_profiles
You should edit all sip profiles that you wish to use (typically internal.xml and external.xml). Adding the following line to tell these modules how to connect to your shared database and to track the active calls.
<param name="odbc-dsn" value="database:username:password"/>
<param name="track-calls" value="true"/>
switch.conf.xml
You should have the following parameters set in switch.conf.xml on both nodes
<param name="switchname" value="fs01"/>
<param name="core-db-dsn" value="database:username:password"/>
<param name="core-recovery-db-dsn" value="database:username:password"/>