» » Управление IAX каналами при большом количестве Asterisk

 

Управление IAX каналами при большом количестве Asterisk

Автор: admin от 14-02-2018, 16:30, посмотрело: 70

Добрый день.



Каждый, кто мало-мальски администрирует Asterisk, сталкивается с такой задачей как объединить несколько серверов между собой. Тут уже не важно какой протокол выбран IAX или SIP, так как не зависимо от протокола будет приблизительно одинаковый набор действий. В этом нет никакой проблемы до тех пор пока у вас сервера можно пересчитать по пальцам одной руки. Если же вам не хватило одной руки, а пальцы на второй уже заканчиваются тогда милости прошу под кат, дабы посмотреть один из способов решения данной проблемы.

Perl скрипт. Суть его проста, он запускается по крону каждые 5 минут, подключается к БД и проверяет для всех ли IAX каналов записанных в таблице hostname_iax есть строки регистрации в таблице hostname_config. Если чего-то не хватает, то скрипт это исправит, естественно он игнорирует IAX канал имя которого совпадает с hostname локального сервера, так как регистрироваться у самого себя идея так себе.



Lua. На данном этапе, получается что у нас информация о каналах реплицируется, сервера сами регистрируются друг у друга. Осталось только решить вопрос с маршрутизацией звонков, в обычном режиме работы для звонка на новый сервер добавляется новый extension, приблизительно такого содержания:



exten => _19xx,1,noop(звонок в Москву)
exten => _19xx,1,dial(sip/${EXTEN},60,r)
exten => _19xx,1,hangup()




Если у вас 10 серверов, то вы должны код выше добавить на все сервера. Это надо упростить, для этого напишем просто один общий extension который будет сам определять куда и как звонить. Для этого мы в таблицу IAX каналов, в столбец setvar добавим информацию о том какие номера обслуживает тот или иной сервер. Например для asRUmoscow основная информация о IAX канале будет выглядеть так:



Управление IAX каналами при большом количестве Asterisk


Тут мы видим в столбце setvar регулярное выражение по которому можно проверить соответствует набранный номер пользователем к этому серверу или нет. Этого более чем достаточно что бы узнать куда хочет позвонить пользователь, осталось только это реализовать.



Для этого у нас есть такой код:



extensions = {
       office = {
           ["_xxxx"] = internal_sip;
      };
} 
-- Функция обработки всех внутренних вызовов
function internal_sip(context, extension)
     	local dialString = getStringDial(extension);
    	app.Dial(dialString,60,'rTt');
end
-- Проверяем обслуживается пользователь локальным сервером или нет
function isLocalPeer(extension)
	local query = string.format("SELECT setvar FROM %s WHERE name='%s'", hostname.."_iax",hostname);	
	local res = assert(con:execute(query));
	local regexp = res:fetch();
	if (rex.find(extension, regexp)) then 
		res:close();
		return true;
	end
	res:close();
	return false;
end
-- Генерируем строку для приложения Dial в зависимости от того 
-- локальный пользователь или удаленный
function asSystem.getStringDial(extension)
	local dial=nil;
	if (isLocalPeer(extension)) then 
		dial = string.format("sip/%s",extension);
	else 
		local query = string.format("SELECT secret FROM %s WHERE name='%s'",hostname.."_iax",hostname);
		local res = assert (con:execute(query));
		local secret = res:fetch();
		query = string.format("SELECT username,setvar FROM %s",hostname.."_iax");
		res = assert (con:execute(query));
		local server_list = res:fetch({},"a");
		local server = nil;
        local findNum = extension;
        while server_list do
		if rex.find(findNum,server_list.setvar) then
			server = server_list.username;
			break;
		end
		server_list = res:fetch({},"a");
	end
        dial = string.format("iax2/%s:%s@%s/%s",hostname,secret,server,extension);
        res:close();
	end
	return dial;
end


Такой не замысловатый код, позволяет не редактировать конфигурационные файлы Asterisk при каждом добавлении нового сервера.



Результаты



Теперь нам особо делать ничего не надо для того что бы добавить новый сервер. Для этого надо выполнить простой набор команд:



Добавить информацию о новой БД в систему репликации:



bucardo add database asRUsmolensk dbname=asrusmolensk dbhost=192.168.15.30 dbuser=bucardo dbpass=Me%gaP@$$
bucardo add dbgroup asRealtime asRUsmolensk:target
bucardo add customname iax_peers asrusmolensk_iax db=asRUsmolensk


Добавить информацию о новом IAX канале в основную БД:



INSERT INTO public.iax_peers(name, type, username, secret, context, host, trunk, auth, deny, permit, qualify,setvar)
	VALUES 
    ('asRUsmolensk','friend','asRUsmolensk', 'IAX_PAS$w0Rd','office','dynamic','yes','md5','0.0.0.0/0.0.0.0','192.168.15.30/255.255.255','yes','^[16]6d{2,2}'), 


После чего подождать 5 минут и IAX каналы сами поднимутся между всеми серверами и сразу можно звонить на новый сервер.



Эти два действия можно завернуть в Ansible playbook и тогда вообще все будет красиво и модно.



Все это позволяет не только быстро добавлять новые сервера, но и менять маршрутизацию с параметрами IAX каналов. Работает это уже не один год, сейчас сеть разрослась до 25 серверов Asterisk и не уверен что это предел.



Если есть замечания и пожелания, милости просим в комментарии или ЛС.

Источник: Хабрахабр

Категория: Программирование

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Добавление комментария

Имя:*
E-Mail:
Комментарий:
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Введите два слова, показанных на изображении: *