Heartbeat 를 이용한 HA 구성을 테스트하는 중이다.
예제는 간단하게 Apache.
어찌저찌… Active-Standby 설정으로 구성을 하긴했는데 내가 원하는 모습이 나오질 않는다.
서비스의 개념으로 한쪽의 Apache 가 내려가면 다른 한쪽의 Apache 가 올라오길 원했는데 안된다.
정상적으로 작동할 때는 Heartbeat 가 내려가거나, 서버가 내려갔을 경우에 작동했다.
흠… 계속 고민중인데 진척이 없다.
Heartbeat 를 이용한 HA 구성을 테스트하는 중이다.
예제는 간단하게 Apache.
어찌저찌… Active-Standby 설정으로 구성을 하긴했는데 내가 원하는 모습이 나오질 않는다.
서비스의 개념으로 한쪽의 Apache 가 내려가면 다른 한쪽의 Apache 가 올라오길 원했는데 안된다.
정상적으로 작동할 때는 Heartbeat 가 내려가거나, 서버가 내려갔을 경우에 작동했다.
흠… 계속 고민중인데 진척이 없다.
아래 내용들은 GCC49 버전으로 컴파일 했을 때 발생한 에러들이다.
GCC46 버전으로 컴파일 시, 다른 에러들이 발생할 수 있다. 가급적 최신의 컴파일러를 사용하자.
Asterisk 컴파일 에러.
컴파일 중 발생한 에러로서, 참조 에러이다. 파일 수정이 필요하다.
creating config.h
[LD] abstract_jb.o acl.o adsi.o alaw.o aoc.o app.o ast_expr2.o ast_expr2f.o asterisk.o astfd.o astmm.o astobj2.o audiohook.o autochan.o autoservice.o backtrace.o bridge.o bridge_after.o bridge_basic.o bridge_channel.o bridge_roles.o bucket.o callerid.o ccss.o cdr.o cel.o channel.o channel_internal_api.o chanvars.o cli.o config.o config_options.o core_local.o core_unreal.o crypt.o data.o datastore.o db.o devicestate.o dial.o dns.o dnsmgr.o dsp.o endpoints.o enum.o event.o features.o features_config.o file.o fixedjitterbuf.o format.o format_cap.o format_pref.o frame.o framehook.o fskmodem.o global_datastores.o hashtab.o heap.o http.o image.o indications.o io.o jitterbuf.o json.o loader.o lock.o logger.o manager.o manager_bridges.o manager_channels.o manager_endpoints.o manager_mwi.o manager_system.o md5.o media_index.o message.o mixmonitor.o named_acl.o netsock.o netsock2.o optional_api.o parking.o pbx.o pickup.o plc.o poll.o presencestate.o privacy.o rtp_engine.o say.o sched.o sdp_srtp.o security_events.o sem.o sha1.o sip_api.o slinfactory.o sorcery.o sounds_index.o srv.o stasis.o stasis_bridges.o stasis_cache.o stasis_cache_pattern.o stasis_channels.o stasis_endpoints.o stasis_message.o stasis_message_router.o stasis_system.o stdtime/localtime.o strcompat.o strings.o stun.o syslog.o taskprocessor.o tcptls.o tdd.o term.o test.o threadpool.o threadstorage.o timing.o translate.o udptl.o ulaw.o utils.o uuid.o version.o xml.o xmldoc.o editline/libedit.a -> asterisk
ast_expr2.o: In function `op_func’:
/usr/local/src/asterisk-12.2.0/main/ast_expr2.y:884: warning: powl has lower than advertised precision
/usr/local/bin/ld: asterisk: local symbol `__progname’ in /usr/lib/crt1.o is referenced by DSO
/usr/local/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
gmake[2]: *** [asterisk] Error 1
gmake[1]: *** [main] Error 2
gmake[1]: Leaving directory `/usr/local/src/asterisk-12.2.0′
*** Error code 2Stop.
make: stopped in /usr/local/src/asterisk-12.2.0
해결책은 해당 에러가 난 후에, main/asterisk.exports 파일에 다음의 패치 내용을 적용해주면 된다.
--- /usr/ports/net/asterisk/work/asterisk-1.8.11.0/main/asterisk.exports 2012-04-01 11:19:50.532808549 -0700
+++ /root/asterisk.exports 2012-04-01 10:43:28.258979089 -0700
@@ -44,6 +44,8 @@
res_srtp;
res_srtp_policy;
secure_call_info;
+ __progname;
+ environ;
local:
*;
};
spandsp 모듈 에러.
spandsp 모듈은 FAX 관련 모듈로 설치시 다음과 같은 오류가 발생했다.
[CC] res_speech.c -> res_speech.o
[LD] res_speech.o -> res_speech.so
[CC] res_fax_spandsp.c -> res_fax_spandsp.o
res_fax_spandsp.c: In function ‘spandsp_v21_new’:
res_fax_spandsp.c:470:52: error: ‘MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE’ undeclared (first use in this function)
p->tone_state = modem_connect_tones_rx_init(NULL, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, spandsp_v21_tone, p);
^
문제의 원인은 낮은 버전의 라이브러리를 설치했기 때문이었다. 내가 설치했던 spandsp 패키지에서 제공하는 헤더파일에는 “MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE” 선언이 없었던 것.
이미 Asterisk 를 설치한 다른 시스템에서 해당 헤더파일을 비교한 후에야 문제를 해결할 수 있었다.
해당 선언이 들어있는 패키지는 spandsp-devel 패키지이다.
그냥 설치하려고 하면 의존성 문제가 발생하므로 이전에 설치한 패키지를 지우고 새로 설치하도록 하자.
pkg delete spandsp
pkg install spandsp-devel
참조 : http://forums.asterisk.org/viewtopic.php?f=1&t=81017
————————————————————————–
하지만 make install 과정에서 asterisk.h 파일을 찾을 수 없다는 에러만 계속 나왔다.
결국 적당한 시점에서 타협을 해야 했는데.. 그냥 pkg 에 올려져 있는 asterisk 를 사용하기로 했다.
설치한 asterisk 버전은 11.8.1 이다.
Freeswitch 를 설치하는데 openssl-1.0 이상 버전을 요구했다.
현재 운용중인 서버 버전은 Debian-6.0
apt-get 으로 설치 가능한 openssl 버전은 0.9.x 버전이었다.
즉, openssl 버전 문제로 정상적인 설치가 안되는 상황.
openssl 최신버전이야 소스 설치를 하면 되겠는데.. 문제는 이미 사용중인 openssl-0.9.x 버전은 어떻게 하느냐였다.
이미 많은 수의 패키지들이 라이브러리를 참조하고 있었다.
실제로 apt-get remove 명령어로 해당 패키지를 지워볼까 생각도 했는데, 의존성 문제로 상당히 많은 수의 패키지들을 같이 지워야 해서 관두었다.
어쩔까…
Linux HanIRC 채널에 문의를 해보니 다행히 답변이 나왔다.
그냥 덮어쓰면 된다는 것.
wget http://openssl.org/source/openssl-1.0.1.tar.gz tar xfz openssl-1.0.1.tar.gz cd openssl-* ./config --prefix=/usr zlib-dynamic --openssldir=/etc/ssl shared make sudo make install
출처 : http://mariobrandt.de/archives/linux/upgrading-openssl-on-debian-6-squeeze-or-ubuntu-8-04-hardy-456
VPS 를 열기 위해 수집한 자료들을 포스팅한다.
개인적으로 국내 블로그 호스팅은 hostple.net 을 이용하고 있고, 이번에 새로 해외 VPS 를 알아보고 vpsfx.com 을 이용하게 되었다.
국내 VPS 정보 정리
여러 국내/국외 호스팅 소개
http://www.xpressengine.com/hosting_info
상세한 비교 설명
https://lael.be/182
국외 VPS 정보 정리.
가격 및 서비스 정보 일람. 한눈에 이해하기 편해서 강추!
http://www.comparevps.com/
여러가지 프로모션 등을 제공하는 걸로 유명한 사이트
http://lowendtalk.com/
실행되는 기본 함수
Freeswitch 에서 Python 스크립트를 호출할 때, 호출하는 주체가 어디냐에 따라 자동으로 실행되는 Default 함수가 달라진다.
– Dialplan 내에서 <action application=”python” data=”mod_fstest.python_example”/> 와 같은 형식으로 호출되는 경우.
호출되는 스크립트 내, handler() 함수가 호출된다.
handler() 함수의 모습은
# APPLICATION # # default name for apps is "handler" it can be overridden with <modname>::<function> # session is a session object # args is all the args passed after the module name def handler(session, args): consoleLog('info', 'Answering call from Python.n')
처럼 되어야 한다.
– fs_cli 등에서 python 명령으로 호출되는 스크립트의 경우.
호출되는 스크립트 내의 fsapi() 함수가 호출된다.
fsapi() 함수의 모습은
# FSAPI CALL FROM CLI, DP HTTP etc # # default name for python FSAPI is "fsapi" it can be overridden with <modname>::<function> # stream is a switch_stream, anything written with stream.write() is returned to the caller # env is a switch_event # args is all the args passed after the module name # session is a session object when called from the dial plan or the string "na" when not. def fsapi(session, stream, env, args): stream.write("w00t!n" + env.serialize())
처럼 되어야 한다.
– fs_cli 등에서 pyrun 명령으로 호출되는 스크립트의 경우,
호출되는 스크립트 내의 runtime() 함수가 호출된다.
runtime() 함수의 모습은
# RUN A FUNCTION IN A THREAD # # default name for pyrun is "runtime" it can be overridden with <modname>::<function> # args is all the args passed after the module name def runtime(args): print args + "n"
처럼 되어야 한다.
지원 API
mod_python 모듈을 이용하여 스크립트 작성시, freeswitch 에서 제공하는 여러가지 API 들을 이용하여 편리하게 프로그래밍을 할 수 있다.
지원하는 API 내용은 mod_lua 와 똑같은 내용의 API 를 지원하며 자세한 기능 및 API 일람은 아래의 링크에서 확인할 수 있다.
mod_lua API 목록: https://wiki.freeswitch.org/wiki/Mod_lua
예제 python Script
예제로 사용한 python script 이다. 원본은 https://wiki.freeswitch.org/wiki/Mod_python#Sample_Python_Scripts 에서 구할 수 있다.
import os from freeswitch import * # HANGUP HOOK # # session is a session object # what is "hangup" or "transfer" # if you pass an extra arg to setInputCallback then append 'arg' to get that value # def hangup_hook(session, what, arg): def hangup_hook(session, what): consoleLog("info","hangup hook for %s!!nn" % what) return # INPUT CALLBACK # # session is a session object # what is "dtmf" or "event" # obj is a dtmf object or an event object depending on the 'what' var. # if you pass an extra arg to setInputCallback then append 'arg' to get that value # def input_callback(session, what, obj, arg): def input_callback(session, what, obj): if (what == "dtmf"): consoleLog("info", what + " " + obj.digit + "n") else: consoleLog("info", what + " " + obj.serialize() + "n") return "pause" # APPLICATION # # default name for apps is "handler" it can be overridden with <modname>::<function> # session is a session object # args is all the args passed after the module name def handler(session, args): consoleLog('info', 'Answering call from Python.n') consoleLog('info', 'Arguments: %sn' % args) session.answer() session.setHangupHook(hangup_hook) session.setInputCallback(input_callback) session.execute("playback", session.getVariable("hold_music")) # FSAPI CALL FROM CLI, DP HTTP etc # # default name for python FSAPI is "fsapi" it can be overridden with <modname>::<function> # stream is a switch_stream, anything written with stream.write() is returned to the caller # env is a switch_event # args is all the args passed after the module name # session is a session object when called from the dial plan or the string "na" when not. def fsapi(session, stream, env, args): stream.write("w00t!n" + env.serialize()) # RUN A FUNCTION IN A THREAD # # default name for pyrun is "runtime" it can be overridden with <modname>::<function> # args is all the args passed after the module name def runtime(args): print args + "n" # BIND TO AN XML LOOKUP # # default name for binding to an XML lookup is "xml_fetch" it can be overridden with <modname>::<function> # params a switch_event with all the relevant data about what is being searched for in the XML registry. # def xml_fetch(params): xml = ''' <?xml version="1.0" encoding="UTF-8" standalone="no"?> <document type="freeswitch/xml"> <section name="dialplan" description="RE Dial Plan For FreeSWITCH"> <context name="default"> <extension name="generated"> <condition> <action application="answer"/> <action application="playback" data="${hold_music}"/> </condition> </extension> </context> </section> </document> ''' return xml
예제로 사용한 dialplan 이다. “5555555”로 전화를 걸면 스크립트가 사용된다.
<include> <extension name="python_test"> <condition field="destination_number" expression="^(5555555)$"> <!-- If you're hosting multiple domains you will want to set the target_domain on these calls so they hit the proper domain after you transfer the caller into the default context. $${domain} is the default domain set from vars.xml but you can set it to any domain you have setup in your user directory. --> <action application="info"/> <action application="python" data="mod_fstest.python_example"/> <!--<action application="set" data="domain_name=$${domain}"/>--> <!-- This example maps the DID 5551212 to ring 1000 in the default context --> <!--<action application="transfer" data="1000 XML default"/>--> </condition> </extension> </include>
작성한 Python 스크립트를 dialplan 에서 호출하기 위해서는, 당연하겠지만 Dialplan 내에서 어떤 스크립트를 호출할지를 지정해 주어야 한다.
<action application=”python” data=”foo.bar”/>
위에 입력한 foo.bar 는 foo package 에 있는 bar 모듈을 호출한다는 설정이다. 뒤에 확장자 .py 를 붙이지 않도록 주의하자.
이 경우, 사용하게 되는 함수는 ‘handler’ 함수이다.
2014-05-06 17:55:40.838121 [NOTICE] mod_python.c:212 Invoking py module: mod_fstest.python_example 2014-05-06 17:55:40.838121 [DEBUG] mod_python.c:281 Call python script 2014-05-06 17:55:40.838121 [INFO] switch_cpp.cpp:1293 Answering call from Python. 2014-05-06 17:55:40.838121 [INFO] switch_cpp.cpp:1293 Arguments:
handler 함수.
# APPLICATION # # default name for apps is "handler" it can be overridden with <modname>::<function> # session is a session object # args is all the args passed after the module name def handler(session, args): consoleLog('info', 'Answering call from Python.n') consoleLog('info', 'Arguments: %sn' % args) session.answer() session.setHangupHook(hangup_hook) session.setInputCallback(input_callback) session.execute("playback", session.getVariable("hold_music"))
인자 값으로 session 과 args 를 입력받는다.
session 은 python 스크립트 내에서 사용되는 freeswitch interface 객체이며, args 는 모듈 호출시 넘겨지는 인자값들이다.
또한, fs_cli 에서 바로 작성한 python 스크립트를 호출할 수 있다. 이 경우, 사용한 명령어에 따라 호출되는 함수가 달라지는데, python 명령으로 호출할 경우, 스크립트 내, ‘fsapi’ 함수가 바로 호출이 된다.
freeswitch@192.168.200.10@internal> python mod_fstest.python_example w00t! 'Event-Name: API Core-UUID: 86d48a48-6f22-475c-89ac-146e6d0217d9 FreeSWITCH-Hostname: MyDebian FreeSWITCH-Switchname: MyDebian FreeSWITCH-IPv4: 10.0.2.10 FreeSWITCH-IPv6: %3A%3A1 Event-Date-Local: 2014-05-06%2017%3A43%3A01 Event-Date-GMT: Tue,%2006%20May%202014%2015%3A43%3A01%20GMT Event-Date-Timestamp: 1399390981818146 Event-Calling-File: switch_loadable_module.c Event-Calling-Function: switch_api_execute Event-Calling-Line-Number: 2406 Event-Sequence: 4158 API-Command: python API-Command-Argument: mod_fstest.python_example ' 2014-05-06 17:43:01.818146 [NOTICE] mod_python.c:212 Invoking py module: mod_fstest.python_example 2014-05-06 17:43:01.818146 [DEBUG] mod_python.c:281 Call python script 2014-05-06 17:43:01.818146 [DEBUG] mod_python.c:284 Finished calling python script
참조 : https://wiki.freeswitch.org/wiki/Mod_python#Sample_Python_Scripts