Asterisk + LUA: швидкий старт

За останній рік на Хабре з'явилося кілька статей про використання диалплана lua в asterisk (раз, два, три, чотири). Це досить цікавий спосіб написання гнучких і потужних диалпланов. Але щоб спробувати такий спосіб написання диалпланов треба витратити певну кількість часу: встановити потрібні бібліотеки, перезібрати з необхідними опціями астеріск.

До того ж у багатьох користувачів asterisk'а різний рівень підготовки: хтось ближче до системного адміністрування або навіть до традиційної телефонії, ніж до програмування. Плюс специфіка телефонії — краще зайвий раз незнайомими експериментами не навантажувати працюючі системи, а проводити тести та експерименти на своєму ноутбуці — доводиться захаращувати систему. Загалом, є чимало причин «відкласти на потім».

У цій статті я хочу показати всім бажаючим і працюють з астериском, як, використовуючи docker, можна швидко відчути смак гнучких сценаріїв lua. А вже потім вирішити чи варто цим користуватися далі на практиці чи ні. (Кому нецікаво читати, а цікаво дивитися і слухати — в кінці тексту 6-хвилинне відео з основними моментами і результатом.)



Вступне слово

В рамках роботи над кількома своїми проектами, слідуючи сучасної тенденції упаковки всього в контейнери, я підготував образ astolua (asterisk + lua). У Dockerfile наведені команди для встановлення asterisk 11, lua 5.1, luarocks (пакетний менеджер для lua), luamongo драйвер для доступу до mongodb), деякі пакети lua rocks. Ви можете в подальшому в репозиторії docker-astolua взяти тільки корисне для себе і зібрати свою робочу конячку.

Безумовно плюсом докера є можливість завантажити образ, провести проби-експерименти-тести, а потім видалити образи, залишивши свою операційну систему в чистоті і звичному порядку.

На основі образу astolua ми створимо свій робочий образ, в якому будемо використовувати тестові файли конфігурації астериска і диалплан на lua.

Підготовка

Нам потрібно docker. Якщо у вас він не встановлений, то, будь ласка, спочатку встановіть docker (офіційна документація, стаття на Хабре).

Також нам потрібно git (установка git

Також відразу зазначу, що моєї робочої є системою Ubuntu 14.04. Якщо ви використовуєте інший Linux, то відмінності в командах по ідеї, не повинно бути, але нюанси не виключені.

Завантаження образу astolua

Затягуємо образ (увага, буде завантажений образ з репозиторію hub.docker.com розміром ~600Мб).

docker pull antirek/astolua


Sample

Клонируем docker-astolua-sample — це заздалегідь заготовлений набір файлів для цієї статті.

git clone https://github.com/antirek/docker-astolua-sample.git
cd docker-astolua-sample


Тепер давайте зупинимося на sample і подивимося вміст директорії.

Файл Dockerfile

Файл для складання нашого робочого образу. В ньому ми вказуємо, що беремо за основу astolua. Потім додаємо скрипт автозавантаження after_start.sh, який буде виконаний при старті контейнера. В консоль, де ми запустимо контейнер, будуть виводитися лог консолі астериска.

Файл build

Всередині файлу команда докера на побудову образу sample з нашого Dockerfile.
docker build -t "astolua:sample" .


Файл run
Всередині файлу команда докера на запуск контейнера на основі образу sample з конфігуруванням необхідних йому ресурсів.

docker run \
-v /etc/localtime:/etc/localtime:ro \
-v $(pwd)/store/etc/asterisk:/etc/asterisk \
-v $(pwd)/store/var/log/asterisk:/var/log/asterisk \
-v $(pwd)/store/var/menu:/var/menu/ \
--net=host \
-i -t "astolua:sample"


Папка store
Папка store містить конфігураційні файли астериска (ті, які зазвичай лежать в /etc/asterisk) і папки для логів і голосових меню.

Команда run найбільш цікава, оскільки тут вказуються необхідні ресурси для контейнера. Наприклад, опцією -v $(pwd)/store/etc/asterisk:/etc/asterisk ми вказуємо, що конфігураційні файли з нашої папки store повинні опинитися всередині контейнера на своєму місці в /etc/asterisk.

Чому команди у файлах? Зручно редагувати команди у файлі, оскільки це прискорює час на протестувати зміни в командах з різними опціями, а також всі зміни ляжуть під контроль версій. І ще зручно потім перенести опції в docker-compose, якщо образ буде використовуватися спільно з іншими.

Повернемося до консолі.

Зробимо образ astolua:sample (в директорії, куди ми склонировали docker-astolua-sample)
./build


Запускаємо asterisk (якщо у вас уже запущений на машині астеріск або інший сервіс, який займає порт 5060, то його краще попередньо зупинити)
./run


В консоль повинен повалиться лог завантаження астериска. Можна протестувати зв'язок.

В конфігураційному файлі астериска sip.conf вказані два абонента 101 і 102 (пароль 1234), а у файлі queues.conf чергу 1234, в яку додано ці два абонента. Налаштуйте свій софтфон або хардфон на 101 абонента і спробуйте зробити дзвінок на абонента 102. (Транков для підключення до зовнішніх voip-сервісів або налаштувань якогось заліза немає, тому диалплан ми потестируем на локальних дзвінки). Інформація про виклик між абонентами повинна з'явитися в консолі астериска.

Абоненти працюють, дзвінки проходять? Ок, значить астеріск в докер-контейнері працює як треба.

Диалплан lua

Диалплан lua знаходиться у файлі extensions.lua. У конфігураційних файлах астериска в папці store/etc/asterisk є приклад працюючого диалплана lua.

У цьому файлі повинні бути правильно описані змінні extensions і hints (в термінології lua — це «таблиці»).

В таблиці extensions містяться контексти і відповідні extensions. Все як у традиційному диалплане. Але кожен extension обробляється своєю функцією, в якій ви можете робити все, що завгодно на lua, при цьому взаємодіючи з астериском через таблиці app і channel.

Найпростіший приклад

extensions = {
["internal"] = {
["_1XX"] = function (context, extension)
-- do something --
app.dial('SIP/'..extension);
-- do something again
end;
}
}


Видно, що через app доступно додаток диалплана Dial, воно бере всі ті ж параметри, що і в традиційному диалплане. Через app доступні всі програми диалплана.

Змінна channel дає доступ до канальним змінним. Ось так, наприклад, отримуємо dialstatus.

extensions = {
["internal"] = {
["_1XX"] = function (context, extension)
-- do something -- 
app.dial('SIP/'..extension);
local dialstatus = channel["DIALSTATUS"]:get();
app.noop('dialstatus: '..dialstatus);
end;
}
}


Ви можете змінити extensions.lua, а потім командою в CLI астериска module reload pbx_lua.so перечитати extensions.lua. Астеріск перевірить синтаксис lua, і якщо все ок, то завантажить його для виконання — можна тестувати зміни.

А що ще можна робити в диалплане lua?

Наприклад, гнучко обробити dialstatus, який буде повернений функцією Dial диалплана. Не треба винаходити ці Goto(s-${DIALSTATUS},1), тепер можна по-людськи написати перевірку статусу

extensions = {
["internal"] = {
["_1XX"] = function (context, extension)
app.dial('SIP/'..extension);

local dialstatus = channel["DIALSTATUS"]:get();
if dialstatus == 'BUSY' then
-- do something 
elseif dialstatus == 'CHANUNAVAIL' then 
-- do another thing
end;
end;
}
}


У прикладі extensions.lua є приклад простого ivr: зателефонувавши на номер 200, ви почуєте запис з файлу /var/menu/demo і зможете перейти далі, натиснувши 1 або 2.

local ivr = function (context, extension) 
app.read("IVR_CHOOSE", "/var/menu/demo", 1, nil, 2, 3);
local choose = channel["IVR_CHOOSE"]:get();

choose if == '1' then
app.queue('1234');
elseif choose == '2' then
dial('internal', '101');
else
app.hangup();
end;
end;


Для людини, що написала пару десятків рядків традиційного диалплана, тут має бути все знайоме. Плюс з'являється вся міць lua і пакетів luarocks. Сподіваюся очевидно, що тут же в диалплане ви можете відправити смс, емейл, покласти дані в бд, взяти дані з бд, а бд може бути будь-яка: mysql, mongodb, redis і т. п., зробити виклик команди, ініціювати ще один дзвінок, зробити крутий роутинг дзвінка по транкам і т. д., не забуваючи, звичайно, що це все працює в рамках астериска, і всі «важкі» завдання краще все-таки вирішувати окремо.

Що далі?

Пропоную:


Сподіваюся, ця стаття буде корисна для швидкого старту, і ви знайдете один вільний зимовий вечір і спробуєте такий спосіб написання диалпланов.



Помилки? Опечятки? Питання? Будь ласка, пишіть.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.