在默认情况下,Asterisk的配置文件都保存在/etc/asterisk目录中,以ini文件的格式保存。我们也可以使用数据库来保存大多数Asterisk配置信息。
Asterisk使用数据库保存配置信息有两种方法:静态和动态,对于不经常修改的配置数据,可以使用静态的方式保存,这些数据都是在Asterisk对应的模块加载时获取配置信息。动态方式适合那些经常变化的数据,例如SIP帐号信息。使用数据库来保存SIP帐号信息还有一个好处:Asterisk会自动把SIP帐号登录Asterisk的相关资料保存到表中,这样大大的方便了管理员检查当前SIP帐号的使用情况和状态。
下面开始介绍Asterisk的数据库获取配置的方法。我使用的是Asterisk版本是 11.0.0。
在这里,我只对Asterisk的基本配置和SIP相关的配置感兴趣,AIX帐号的配置和SIP的配置应该类似,不想多作分析。
1. 基本介绍
1.1. 获取数据的方法
配置信息可以保存在多种数据库中,下面是Asterisk支持的数据库的列表和对应的模块:
l odbc res_config_odbc
l sqlite res_config_sqlite
l pgsql res_config_pgsql
l curl res_config_curl
l ldap res_config_ldap
为了通用性,我选择了ODBC作为获得和修改Asterisk配置信息的方式,数据库使用mysql。在这里我不介绍如何安装unixODBC和mysql,只对相关的表和配置文件做介绍。
1.2. 使用到的表结构
1.2.1. 静态配置表
CREATE TABLE `ast_config` ( `id` int(11) NOT NULL auto_increment, `cat_metric` int(11) NOT NULL default '0', `var_metric` int(11) NOT NULL default '0', `commented` int(11) NOT NULL default '0', `filename` varchar(128) NOT NULL default '', `category` varchar(128) NOT NULL default 'default', `var_name` varchar(128) NOT NULL default '', `var_val` varchar(128) NOT NULL default '', PRIMARY KEY (`id`), KEY `filename_comment` (`filename`,`commented`) ) |
这个表结构是一个通用的保存各种.conf文件信息的表结构。Asterisk可以让模块的配置信息保存在一个表中,或者分别保存在不同的表中。 |
下面是表的说明
Column name | Column type | Description |
id | Serial, auto-incrementing | An auto-incrementing unique value for each row in the table. |
cat_metric | Integer | The weight of the category within the file. A lower metric means it appears higher in the file (see the sidebar). context类型的权重 |
var_metric | Integer | The weight of an item within a category. A lower metric means it appears higher in the list (see the sidebar). This is useful for things like codec order in sip.conf, or iax.conf where you want disallow=all to appear first (metric of 0), followed by allow=ulaw (metric of 1), then allow=gsm (metric of 2). 变量的权重 |
filename | Varchar 128 | The filename the module would normally read from the hard drive of your system (e.g., musiconhold.conf, sip.conf, iax.conf, etc.). 文件名 |
category | Varchar 128 | The section name within the file, such as [general]. Do not include the square brackets around the name when saving to the database. 类型 |
var_name | Varchar 128 | The option on the left side of the equals sign (e.g., disallow is the var_name in disallow=all). 名字 |
var_val | Varchar 128 | The value of an option on the right side of the equals sign (e.g., all is the var_val in disallow=all). 值 |
commented | Integer | Any value other than 0 will evaluate as if it were prefixed with a semicolon in the flat file (commented out). 注解 |
1.2.2. SIP用户表
SIP用户的存储方式在不同的Asterisk版本中差异很大,当看网上的文档的时候很容易犯迷糊,正确的表结构是在Asterisk源码包的下面目录中:
[root@kernel asterisk-11.0.0]# ls contrib/realtime/mysql/sippeers.sql contrib/realtime/mysql/sippeers.sql |
具体的表结构是:
# # Table structure for table `sippeers` #
CREATE TABLE IF NOT EXISTS `sippeers` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL, `ipaddr` varchar(15) DEFAULT NULL, `port` int(5) DEFAULT NULL, `regseconds` int(11) DEFAULT NULL, `defaultuser` varchar(10) DEFAULT NULL, `fullcontact` varchar(35) DEFAULT NULL, `regserver` varchar(20) DEFAULT NULL, `useragent` varchar(20) DEFAULT NULL, `lastms` int(11) DEFAULT NULL, `host` varchar(40) DEFAULT NULL, `type` enum('friend','user','peer') DEFAULT NULL, `context` varchar(40) DEFAULT NULL, `permit` varchar(40) DEFAULT NULL, `deny` varchar(40) DEFAULT NULL, `secret` varchar(40) DEFAULT NULL, `md5secret` varchar(40) DEFAULT NULL, `remotesecret` varchar(40) DEFAULT NULL, `transport` enum('udp','tcp','udp,tcp','tcp,udp') DEFAULT NULL, `dtmfmode` enum('rfc2833','info','shortinfo','inband','auto') DEFAULT NULL, `directmedia` enum('yes','no','nonat','update') DEFAULT NULL, `nat` enum('yes','no','never','route') DEFAULT NULL, `callgroup` varchar(40) DEFAULT NULL, `pickupgroup` varchar(40) DEFAULT NULL, `language` varchar(40) DEFAULT NULL, `allow` varchar(40) DEFAULT NULL, `disallow` varchar(40) DEFAULT NULL, `insecure` varchar(40) DEFAULT NULL, `trustrpid` enum('yes','no') DEFAULT NULL, `progressinband` enum('yes','no','never') DEFAULT NULL, `promiscredir` enum('yes','no') DEFAULT NULL, `useclientcode` enum('yes','no') DEFAULT NULL, `accountcode` varchar(40) DEFAULT NULL, `setvar` varchar(40) DEFAULT NULL, `callerid` varchar(40) DEFAULT NULL, `amaflags` varchar(40) DEFAULT NULL, `callcounter` enum('yes','no') DEFAULT NULL, `busylevel` int(11) DEFAULT NULL, `allowoverlap` enum('yes','no') DEFAULT NULL, `allowsubscribe` enum('yes','no') DEFAULT NULL, `videosupport` enum('yes','no') DEFAULT NULL, `maxcallbitrate` int(11) DEFAULT NULL, `rfc2833compensate` enum('yes','no') DEFAULT NULL, `mailbox` varchar(40) DEFAULT NULL, `session-timers` enum('accept','refuse','originate') DEFAULT NULL, `session-expires` int(11) DEFAULT NULL, `session-minse` int(11) DEFAULT NULL, `session-refresher` enum('uac','uas') DEFAULT NULL, `t38pt_usertpsource` varchar(40) DEFAULT NULL, `regexten` varchar(40) DEFAULT NULL, `fromdomain` varchar(40) DEFAULT NULL, `fromuser` varchar(40) DEFAULT NULL, `qualify` varchar(40) DEFAULT NULL, `defaultip` varchar(40) DEFAULT NULL, `rtptimeout` int(11) DEFAULT NULL, `rtpholdtimeout` int(11) DEFAULT NULL, `sendrpid` enum('yes','no') DEFAULT NULL, `outboundproxy` varchar(40) DEFAULT NULL, `callbackextension` varchar(40) DEFAULT NULL, `timert1` int(11) DEFAULT NULL, `timerb` int(11) DEFAULT NULL, `qualifyfreq` int(11) DEFAULT NULL, `constantssrc` enum('yes','no') DEFAULT NULL, `contactpermit` varchar(40) DEFAULT NULL, `contactdeny` varchar(40) DEFAULT NULL, `usereqphone` enum('yes','no') DEFAULT NULL, `textsupport` enum('yes','no') DEFAULT NULL, `faxdetect` enum('yes','no') DEFAULT NULL, `buggymwi` enum('yes','no') DEFAULT NULL, `auth` varchar(40) DEFAULT NULL, `fullname` varchar(40) DEFAULT NULL, `trunkname` varchar(40) DEFAULT NULL, `cid_number` varchar(40) DEFAULT NULL, `callingpres` enum('allowed_not_screened','allowed_passed_screen','allowed_failed_screen','allowed','prohib_not_screened','prohib_passed_screen','prohib_failed_screen','prohib') DEFAULT NULL, `mohinterpret` varchar(40) DEFAULT NULL, `mohsuggest` varchar(40) DEFAULT NULL, `parkinglot` varchar(40) DEFAULT NULL, `hasvoicemail` enum('yes','no') DEFAULT NULL, `subscribemwi` enum('yes','no') DEFAULT NULL, `vmexten` varchar(40) DEFAULT NULL, `autoframing` enum('yes','no') DEFAULT NULL, `rtpkeepalive` int(11) DEFAULT NULL, `call-limit` int(11) DEFAULT NULL, `g726nonstandard` enum('yes','no') DEFAULT NULL, `ignoresdpversion` enum('yes','no') DEFAULT NULL, `allowtransfer` enum('yes','no') DEFAULT NULL, `dynamic` enum('yes','no') DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`), KEY `ipaddr` (`ipaddr`,`port`), KEY `host` (`host`,`port`) ) |
看起来这个表字段很多很吓人,其实最近本的配置就下面几项:
l Name 帐号名字
l Host 设置成dynamic
l Context 设置对应的context
l Type 选择friend
l Secret 帐号密码明文
其他很多字段都是SIP帐号登录时的数据字段。
1.3. 使用到的配置文件
1.3.1. extconfig.conf
最基本的配置文件是extconfig.conf,这个配置文件定义了哪些模块使用数据库的配置,确定了SIP帐号对应的表格。这个配置文件的注释已经基本介绍了它的使用方法,不过没有具体的表的结构。本文上面已经介绍了两个相关的表结构。其他表结构可以在Asterisk源码包的contrib/realtime/目录下找找。
1.3.2. res_odbc.conf
由于我选择了ODBC的数据库连接方式,所以必然的需要ODBC的资源配置。
这个配置文件中,我使用了原来的配置参数:
[asterisk] enabled => yes dsn => asterisk |
如果是使用yum安装的unixODBC,Asterisk这个数据源在/etc/odbc.ini中定义。
感觉就是:
[asterisk] Driver = MySQL Database = asterisk Servername = localhost UserName = root Password = xxxxx |
相关的设备在/etc/odbcinst.ini中定义:
[MySQL] Description = ODBC for MySQL Driver = /usr/local/lib/libmyodbc5.so Setup = /usr/local/lib/libmyodbc5w.so FileUsage = 1 |
1.3.3. Sip.conf
在sip.conf中有一些和动态实时数据库配置相关的项,这些想对整个配置的实现影响不大,但是涉及是否建立内存缓存,影响性能。
1.3.4. modules.conf
这个文件是Asterisk加载模块的配置文件。要实现配置数据保存到数据库中,必须修改一下加载方法。
下面是modules.conf中相应的注意事项:
; Any modules that need to be loaded before the Asterisk core has been ; initialized (just after the logger has been initialized) can be loaded ; using 'preload'. This will frequently be needed if you wish to map all ; module configuration files into Realtime storage, since the Realtime ; driver will need to be loaded before the modules using those configuration ; files are initialized. ; ; An example of loading ODBC support would be: preload => res_odbc.so preload => res_config_odbc.so |
任何模块想在Asterisk核心模块初始化之前加载,可以使用preload方式加载。实时驱动相关的模块需要在其他模块加载前加载,这样才能让其他模块使用数据库的配置信息。 |
2. 静态配置
在这里稍微介绍一个简单的静态配置例子,选择的模块是:musiconhold.conf。
在配置静态配置文件之前,建议先看看extconfig.conf文件的下面内容:
; ; The following files CANNOT be loaded from Realtime storage: ; asterisk.conf ; extconfig.conf (this file) ; logger.conf ; ; Additionally, the following files cannot be loaded from ; Realtime storage unless the storage driver is loaded ; early using 'preload' statements in modules.conf: ; manager.conf ; cdr.conf ; rtp.conf ; ; Named ACLs specified in realtime also can not be used ; from manager.conf unless the storage driver is preloaded. ; Attempting to use a realtime stored named ACL before the ; driver is loaded will result in an invalid ACL which ; rejects all addresses. |
2.1. 删除配置文件
$ cd /etc/asterisk $ mv musiconhold.conf musiconhold.conf.old |
2.2. 检查模块加载情况
*CLI> core restart now *CLI> moh show classes *CLI> |
2.3. 插入数据记录
INSERT INTO ast_config (filename,category,var_name,var_val) VALUES ('musiconhold.conf','default','mode','files'); INSERT INTO ast_config (filename,category,var_name,var_val) VALUES ('musiconhold.conf','default','directory','/var/lib/asterisk/moh'); |
asterisk=# SELECT filename,category,var_name,var_val FROM ast_config;
filename | category | var_name | var_val ------------------+----------------+--------------+------------------------ musiconhold.conf | default | mode | files musiconhold.conf | default | directory | /var/lib/asterisk/moh (2 rows) |
2.4. 设置extconfig.conf
在extconfig.conf中加入:
musiconhold.conf => odbc,asterisk,ast_config |
2.5. 重载模块
kernel*CLI> module reload extconfig == Parsing '/etc/asterisk/extconfig.conf': Found == Binding musiconhold.conf to odbc/asterisk/ast_config |
kernel*CLI> module reload res_musiconhold.so -- Reloading module 'res_musiconhold.so' (Music On Hold Resource) |
2.6. 查看数据库中的配置
kernel*CLI> moh show classes Class: default Mode: files Directory: /var/lib/asterisk/moh |
3. 动态配置SIP用户信息
在开始做SIP的动态加载之前,先看看extconfig.conf配置文件中的这部分:
; Realtime configuration engine ; ; maps a particular family of realtime ; configuration to a given database driver, ; database and table (or uses the name of ; the family if the table is not specified ; ;example => odbc,asterisk,alttable,1 ;example => mysql,asterisk,alttable,2 ;example2 => ldap,"dc=oxymium,dc=net",example2 ; ; Additionally, priorities are now supported for use as failover methods ; for retrieving realtime data. If one connection fails to retrieve any ; information, the next sequential priority will be tried next. This ; especially works well with ODBC connections, since res_odbc now caches ; when connection failures occur and prevents immediately retrying those ; connections until after a specified timeout. Note: priorities must ; start at 1 and be sequential (i.e. if you have only priorities 1, 2, ; and 4, then 4 will be ignored, because there is no 3). ; ; "odbc" is shown in the examples below, but is not the only valid realtime ; engine. There is: ; odbc ... res_config_odbc ; sqlite ... res_config_sqlite ; pgsql ... res_config_pgsql ; curl ... res_config_curl ; ldap ... res_config_ldap ; ; Note: The res_config_pgsql and res_config_sqlite backends configure the ; database used in their respective configuration files and ignore the ; database name configured in this file. ; ;iaxusers => odbc,asterisk ;iaxpeers => odbc,asterisk ;sippeers => odbc,asterisk ;sipregs => odbc,asterisk ; (avoid sipregs if possible, e.g. by using a view) ;voicemail => odbc,asterisk ;extensions => odbc,asterisk ;meetme => mysql,general ;queues => odbc,asterisk ;queue_members => odbc,asterisk ;acls => odbc,asterisk ;musiconhold => mysql,general ;queue_log => mysql,general ; sippeers => odbc,asterisk ; ; While most dynamic realtime engines are automatically used when defined in |
3.1. 修改extconfig.conf
就修改下面一行,把下面行的注释符去掉。
sippeers => odbc,asterisk |
3.2. 修改sip.conf
把下面行的注释符去掉。没考证过不做这步有什么影响。^^
rtupdate=yes ; Send registry updates to database using realtime? (yes|no) |
3.3. 添加记录
INSERT INTO sippeers (NAME, HOST,TYPE,context,secret) VALUES ('2012', 'dynamic','friend', 'jluotest','2012') |
3.4. 重载模块
kernel*CLI> module reload extconfig == Parsing '/etc/asterisk/extconfig.conf': Found == Binding musiconhold.conf to odbc/asterisk/ast_config == Binding sippeers to odbc/asterisk/sippeers kernel*CLI> sip reload Reloading SIP == Parsing '/etc/asterisk/sip.conf': Found == Parsing '/etc/asterisk/users.conf': Found == Using SIP CoS mark 4 == Parsing '/etc/asterisk/sip_notify.conf': Found |
3.5. 查看
kernel*CLI> sip show users Username Secret Accountcode Def.Context ACL ForcerPort 2134 not_very_secret jluotest No No 2136 peekaboo jluotest No No 2133 peekaboo jluotest No No |
看到的只有在sip.conf中配置的用户。
3.6. 用2011登录
似乎默认情况下不会显示对应的数据库中配置的用户,只有该用户登录后才显示。下面是2011登录后,再查看SIP用户列表的情况:
-- Unregistered SIP '2011' -- Registered SIP '2011' at 192.168.0.11:4604 > Saved useragent "Linphone/3.5.2 (eXosip2/3.6.0)" for peer 2011 kernel*CLI> sip show users Username Secret Accountcode Def.Context ACL ForcerPort 2134 not_very_secret jluotest No No 2136 peekaboo jluotest No No 2133 peekaboo jluotest No No 2011 2011 jluotest No No |
4. 后记
本文档只是我的一个实践记录,有很多不完善和缺失,但是能与大家的实践做一个对比。
一个更完善的配置需要更加充分地分析SIP配置和对Asterisk的各个模块的配置信息有更充分的了解。