Как стать автором
Обновить

Более продвинутый auto provisioning для Fanvil

На хабре уже есть статья похожей тематики («Auto provisioning для Fanvil BW210P»), но автор не учел некоторые моменты критичные в моем случае:
  • У разных моделей Fanvil конфигурационные файлы отличаются, хотя и не существенно;
  • Зачем ограничивать себя только настройкой SIP;
  • IP телефоны других производителей тоже умеют автонастройку;
  • Шифровать конфиги не обязательно.

Мой способ тоже не универсальный и требует доработки (особенно в отношении третьего пункта).

Конфигурация организуется за счет шаблонов в которые подставляются данные из csv таблицы (первой строкой таблиы является имя переменной в шаблоне), генератор организован средствами lua, который изучался параллельно.

Пример csv:
mac version model host domain sip_user sip_pass sip_server logo
001122334455 2.0003 Fanvil C62 sip103 voip.lan 103 PassWord 10.10.20.20 SIP 103
aabbccddeeff 2.0003 Fanvil C58 sip101 voip.lan 101 PassWord 10.10.20.20 SIP 101
665533114422 2.0003 Fanvil C58 sip102 voip.lan s02 PassWord 10.10.20.20 SIP 102

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

Пример шаблона:

Отмечу, что Fanvil отлично принимает не полные конфигурационные файлы, что сокращает размер шаблона.

fanvil_c58.cfg
<<VOIP CONFIG FILE>>$version

<GLOBAL CONFIG MODULE>
WAN Mode           :DHCP
Default Protocol   :2
Enable DHCP        :1
DHCP Auto DNS      :1
DHCP Auto Time     :1
Domain Name        :$domain
Host Name          :$host
Enable PPPoE       :0
RTP Initial Port   :10000
RTP Port Quantity  :2000
SNTP Server        :10.10.10.1
Enable SNTP        :1
Time Zone          :40
Time Zone Name     :IST_003
Enable DST         :0
SNTP Timeout       :60

<LAN CONFIG MODULE>
Enable Bridge Mode :1
Enable Port Mirror :0

<TELE CONFIG MODULE>
Dial by Timeout    :1
Dial Timeout value :2

<DSP CONFIG MODULE>
--Port Config--    :
P1 General Spk Vol :4
P1 General Mic Vol :3
P1 Headset Vol     :5
P1 Ring in Headset :0
P1 Auto Headset    :1
P1 Headset Ring Vol:5
P1 HandFree Vol    :5
P1 RingTone Vol    :1
P1 Voice Codec1    :G722/8000
P1 Voice Codec2    :PCMU/8000
P1 Voice Codec3    :PCMA/8000
P1 Voice Codec4    :G729/8000
P1 Voice Codec5    :
P1 Voice Codec6    :
--Codec Config--   :
Codec1 Format      :G722/8000;payload=9;
Codec2 Format      :PCMU/8000;payload=0;
Codec3 Format      :PCMA/8000;payload=8;
Codec4 Format      :G723/8000;payload=4;bitrate=6.3;
Codec5 Format      :G729/8000;payload=18;annexb=no;
Codec6 Format      :G726-32/8000;payload=2;
Codec7 Format      :telephone-event/8000;payload=101;

<SIP CONFIG MODULE>
SIP  Port          :5060
--SIP Line List--  :
SIP1 Phone Number  :$sip_user
SIP1 Display Name  :$sip_user
SIP1 Sip Name      :$sip_user
SIP1 Register Addr :$sip_server
SIP1 Register Port :5060
SIP1 Register User :$sip_user
SIP1 Register Pswd :$sip_pass
SIP1 Enable Reg    :1
SIP1 Always FWD    :0
SIP1 Busy FWD      :0
SIP1 No Answer FWD :0
SIP1 Always FWD Num:
SIP1 Busy FWD Num  :
SIP1 NoAnswer FWD N:
SIP1 FWD Timer     :60
SIP1 Ring Type     :0
SIP1 Auto Answer   :0
SIP1 NoAnswerTime  :60
SIP1 VoiceCodecMap :G722,G711A,G711U

<MMI CONFIG MODULE>
Telnet Port        :23
Web Port           :88
Web Server Type    :1
Https Web Port     :443
Remote Control     :1
Enable MMI Filter  :0
Telnet Prompt      :How do you do?
--MMI Account--    :
Account1 Name      :Admin
Account1 Password  :PassWord
Account1 Level     :10

<QOS CONFIG MODULE>
Enable VLAN        :0
Enable diffServ    :0
LLDP Transmit      :0
LLDP Refresh Time  :60
LLDP Learn Policy  :0
Singalling DSCP    :-1
Voice DSCP         :46
VLAN ID            :256
Signalling Priority:0
Voice Priority     :0
VLAN Recv Check    :1
Enable PVID        :0
PVID Value         :254

<AAA CONFIG MODULE>
Enable Syslog      :0
Syslog address     :0.0.0.0
Syslog port        :514

<PHONE CONFIG MODULE>
Menu Password      :31415
KeyLock Password   :
Fast Keylock Code  :
Enable KeyLock     :0
LCD Title          :$logo
LCD Constrast      :5
LCD Luminance      :1
Backlight Off Time :86400
Enable Power LED   :1
Time Display Style :0
Enable TimeDisplay :1
Date Display Style :9
Date Separator     :0
--Function Key--   :
Fkey1 Type         :1
Fkey1 Value        :1000@1/p**1000
Fkey1 Title        :
Fkey2 Type         :1
Fkey2 Value        :2000@1/p**2000
Fkey2 Title        :
Fkey3 Type         :1
Fkey3 Value        :5000@1/p**5000
Fkey3 Title        :
Fkey4 Type         :1
Fkey4 Value        :8000@1/p**8000
Fkey4 Title        :

<AUTOUPDATE CONFIG MODULE>
Download Username  :
Download Password  :
FDPS Enable        :1
Config File Name   :
Config File Key    :
Common Cfg File Key:
Download Server IP :
Download Protocol  :2
Download Mode      :0
Download Interval  :1
DHCP Option        :66
Save Provision Info:0

<DHCP CONFIG MODULE>
DHCP Server Type   :0

<NAT CONFIG MODULE>
Enable Nat         :0

<VPN CONFIG MODULE>
VPN mode           :0

<DOT1X CONFIG MODULE>
Xsup Enable        :0

<TR069 CONFIG MODULE>
Enable TR069       :0
<<END OF FILE>>

Для остальных моделей шаблон схожий. Вообще C62 вполне можно настроить данным шаблоном, за исключением доп. панелей.


И собственно генератор:

#!/usr/bin/lua
--Да, можно в csv задавать имя шаблона на прямую, но пока так
local patterns = {
  ["Fanvil C62"] = "fanvil_c62.cfg",
  ["Fanvil C58"] = "fanvil_c58.cfg",
  ["Fanvil X5"] = "fanvil_x5.cfg",
}
--Имя и путь к csv
local data = "phones.csv"
local field={}

--Эту функцию честно спер
local function split(str, sep)
  sep = sep or ';'
  fields={}
  local matchfunc = string.gmatch(str, "([^"..sep.."]+)")
  if not matchfunc then 
    return {str} 
  end
  for str in matchfunc do
    table.insert(fields, str)
  end
  return fields
end

for line in io.lines(data) do
  --Костыль для отделения строки с заголовком от данных
  if values ~= true then
    mask = split(line) 
    values = true
  else
    for k,v in pairs(split(line)) do
      field[mask[k]] = v
    end
    config = assert(io.open(field["mac"]..".cfg", "w"))
    --FIXME: Проверка на существование шаблона!!!
    pattern = patterns[field["model"]]
    for opt in io.lines(pattern) do
      --Оказалось в конце каждой строки был \r который воспринимался lua как символ
      opt = string.gsub(opt, "\r", "")
      if string.find(opt, "%$") then
        --FIXME:Перестать заменять строку до конца..тогда можно и XML ковырять
        config:write(string.sub(string.match(opt, '^.-%$'),1,-2)..tostring(field[string.sub(string.match(opt,'%$.-$'),2)]).."\n")
      else
        config:write(opt.."\n")
      end
    end
  end
end

Генератор запускается без опций и в каталоге появляются необходимые файлы.

Кончено, можно и нужно сделать лучше: добавить проверку на существование шаблона, выборочная переконфигурация аппаратов, перейти от формы $var к $var$ для возможности добавления данных в середину строки (может есть стратегия получше), что позволит генерировать конфигурации для иных производителей и аппаратов (например, таким грубым способом редактировать XML шаблоны). Возможно полностью отказаться от переменных в шаблонах, используя вместо них начало строки.

Но на данный момент генератор выполняет свои функции на 100%.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.