Skip to content

Mr-Method/Ponmon_Menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

#StandWithUkraine

Stand With Ukraine

Кастомні розширення меню для модуля Ponmon білінгової системи Nodeny

Опис

В процесі розробки модуля Ponmon люди часто просили специфічні для них функції, які не входять в стандартний функціонал, а інколи й суперечливі.

Я вирішив, що краще буде розробити розширення для меню, яке буде дозволяти користувачам додавати власні пункти меню, які будуть доступні тільки для них, але зробити їх доступними для інших.

Пропоную обмінюватись такими патчами в цьому репозиторії.

Правила

  • Хочете додати файл - своріть форк цього репозиторію.
  • Кожен функціонал меню повинен бути в окремому файлі, який має починатись з patch.web.ajOnuMenu.
  • В назві файлу в дужках вказується вендор, модель та/або тип , а вкінці описується функціонал, наприклад:
    • (Bdcom_epon)_reboot.pl
    • (ZteC6)_LinkTest.pl
  • Якщо вже існує такий файл, але він вам не підходить, то можна додати новий файл з іншим ім'ям в кінці назви.
  • В першому рядку функції потрібно вказувати дату останньої зміни файлу. Також можна вказати контакти автора.
  • Додавати нові файли можна через створення запиту на злиття.

## Розробка кастомних меню для ONU

Модуль Ponmon підтримує розширення функціоналу через додаткові меню для ONU. Ці меню дозволяють виконувати специфічні команди на обладнанні різних вендорів.

Ця документація надає повний огляд системи розширення меню ONU та дозволяє розробникам створювати власні функції для специфічних потреб обладнання.

Архітектура меню

Система хуків (Hooks)

Система меню працює через хуки - точки розширення в базовому коді web/ajOnuMenu.pl. Кожен модуль-розширення може додавати елементи меню до різних категорій.

Доступні хуки меню з врахуванням прав доступу

Хук Призначення Приклад функцій
menu_bind Основні функції прив'язки Інформація, Link Test
menu_reboot Функції перезавантаження Reboot ONU, Remove ONU
menu_settings Налаштування портів Enable/Disable порт
menu_macs Робота з MAC адресами Перегляд MAC на ONU
menu_super Адміністративні функції Реконфігурація ONU
subs Додання функцій Власні процедури

Структура patch-файлу

ACTION директиви

Кожен patch-файл використовує ACTION директиви для інтеграції з базовим кодом:

#<ACTION> file=>'web/ajOnuMenu.pl',hook=>'menu_bind', after=>['Ponmon']
        push @menuItems, { 
            order => 21, 
            title => L('Інформація'), 
            act=>'checkInfoOnuBdcom' 
        } if lc($p{vendor}) =~ 'bdcom' && (lc($p{model}) =~ '33' || lc($p{model}) =~ m/^p36/i);

#<ACTION> file=>'web/ajOnuMenu.pl',hook=>'subs', after=>['Ponmon']

sub act_checkInfoOnuBdcom {
    # Реалізація функції
}

Параметри ACTION

Параметр Призначення Приклад
file Цільовий файл для патчування 'web/ajOnuMenu.pl'
hook Назва хука 'menu_bind', 'subs'
after Після якого модуля вставляти ['Ponmon'], 'Ponmon'

Параметри елементу меню

{
    order => 21,                    # Порядок відображення (чим менше - тим вище)
    title => L('Назва пункту'),     # Локалізована назва
    act => 'functionName',          # Назва функції-обробника
    param => { key => 'value' }     # Додаткові параметри (опціонально)
}

Умови відображення

Меню можуть відображатися залежно від:

# По вендору
if lc($p{vendor}) =~ 'bdcom'

# По моделі  
if lc($p{model}) =~ '33'

# По комбінації
if lc($p{vendor}) =~ /^zte/i && $p{model} =~ /c6/i

# З правами доступу
if lc($p{vendor}) =~ 'stels11' && $ses::debug

Типи меню з прикладами

1. Інформаційні меню (menu_bind)

Призначення: Перегляд стану ONU, Link Test, отримання додаткової інформації.

#<ACTION> file=>'web/ajOnuMenu.pl',hook=>'menu_bind', after=>['Ponmon']
        push @menuItems, { 
            order => 20, 
            title => L('Перегляд стану'), 
            act=>'checkInfoZte' 
        } if lc($p{vendor}) =~ /^zte/i;

sub act_checkInfoZte {
    my $attr = shift;
    return $ajax_url->a($lang::btn_Execute, act=>'checkInfoZte', go=>1) 
        unless ses::input_int('go');
    
    my $tc = _telnetConnect($attr);
    ToLog(L('Запросив Detail Info ОНУ sn=[]', $attr->{sn}));
    
    $attr->{info} = _chkInfo($attr, $tc) if $tc;
    _telnetClose($tc);
    
    return $attr->{info}{err} if defined $attr->{info}{err};
    return $attr->{info}{ok} if defined $attr->{info}{ok};
}

2. Меню перезавантаження (menu_reboot)

Призначення: Перезавантаження, видалення ONU.

#<ACTION> file=>'web/ajOnuMenu.pl',hook=>'menu_reboot', after=>['Ponmon']
        push @menuItems, { 
            order => 21, 
            title => L('Перезавантаження ONU'), 
            act=>'rebootOnuBdcom' 
        } if lc($p{vendor}) =~ 'bdcom';

sub act_rebootOnuBdcom {
    my $attr = shift;
    my $sn = $attr->{sn};
    
    # Підготовка серійного номера для EPON
    $sn =~ s/[\:\-\.]//g;
    $sn =~ s/(....)(?=.)/$1\./g if $attr->{pon_type} eq 'epon';
    
    return $ajax_url->a($lang::btn_Execute, act=>'rebootOnuBdcom', go=>1) 
        unless ses::input_int('go');
    
    my $tc = _telnetConnect($attr);
    _tnCmd($tc, "\n");
    
    if ($tc->last_prompt() =~ m/\#$/) {
        _tnCmd($tc, "epon reboot onu mac-address $sn");
        $tc->waitfor('Are you sure to reboot the ONU(y/n)?');
        _tnCmd($tc, "y");
        $attr->{reconf}{ok} = "Reboot ONU sn=$sn";
    } else { 
        $attr->{reconf}{err} = "not in 'enable' mode"; 
    }
    
    _telnetClose($tc);
    return $attr->{reconf}{err} // $attr->{reconf}{ok} // "Backend not defined";
}

3. Меню налаштувань (menu_settings)

Призначення: Увімкнення/вимкнення портів, зміна конфігурації.

#<ACTION> file=>'web/ajOnuMenu.pl',hook=>'menu_settings', after=>['Ponmon']
        push @menuItems, { 
            order => 21, 
            title => L('Вкл порт ONU'), 
            act=>'enableOnuBdcom' 
        } if lc($p{vendor}) =~ 'bdcom';

sub act_enableOnuBdcom {
    my $attr = shift;
    return $ajax_url->a($lang::btn_Execute, act=>'enableOnuBdcom', go=>1) 
        unless ses::input_int('go');
    
    my $tc = _telnetConnect($attr);
    
    if ($tc->last_prompt() =~ m/\#$/) {
        _tnCmd($tc, "config");
        _tnCmd($tc, "interface $attr->{name}");
        _tnCmd($tc, "no shutdown");
        _tnCmd($tc, "exit");
        _tnCmd($tc, "write");
        $attr->{result} = "Port enabled for $attr->{name}";
    }
    
    _telnetClose($tc);
    return $attr->{result};
}

4. Спеціальні функції з формами

Link Test з параметрами:

sub act_linkTestZteC6 {
    my $attr = shift;
    my $tests = ses::input_int('tests') || 100;
    
    # Форма для введення параметрів
    my $form = _(
        '[p][p][p][p]',
        $ajax_url->a(L('Історія тестів'), act=>'linkTestHistory'),
        L('Кількість тестів'),
        v::tag('input', type=>'number', name=>'tests', value=>$tests, 
               size=>16, min=>1, max=>100, 'required'),
        v::submit($lang::btn_Execute)
    );
    
    return $ajax_url->form(-class=>'ajax', act=>'linkTestZteC6', go=>1, 
                          -method=>'post', $form) unless ses::input_int('go');
    
    # Виконання тесту
    my $tc = _telnetConnect($attr);
    # ... логіка тестування ...
    
    # Збереження результатів в БД
    Db->do("INSERT INTO `onu_link_test` SET `sn`=?, `tests`=?, `result`=?, 
            `admin`=?, `time`=UNIX_TIMESTAMP()",
            $attr->{sn}, $tests, $result_count, Adm->id);
}

Робота з Telnet підключеннями

Базові функції

sub _telnetConnect {
    my $attr = shift;
    # Підключення до OLT через Telnet
    # Повертає об'єкт з'єднання або undef
}

sub _tnCmd {
    my ($tc, $cmd, $options) = @_;
    # Виконання команди через Telnet
    # Повертає результат виконання
}

sub _telnetClose {
    my $tc = shift;
    # Закриття Telnet з'єднання
}

sub _tnError {
    my ($tc, $msg) = @_;
    _telnetClose($tc);
    return "Error: $msg";
}

Обробка prompt'ів

# Перевірка режиму enable
if ($tc->last_prompt() =~ m/\#$/) {
    # Увійшли в enable режим
}

# Перевірка config режиму  
if ($tc->last_prompt() =~ m/\(config\)\#/) {
    # Увійшли в config режим
}

# Перевірка interface режиму
if ($tc->last_prompt() =~ m/\(config-if.*\)\#/) {
    # Увійшли в режим конфігурації інтерфейсу
}

Обробка серійних номерів

# Для EPON обладнання BDCOM
my $sn = $attr->{sn};
$sn =~ s/[\:\-\.]//g;                    # Видалення роздільників
$sn =~ s/(....)(?=.)/$1\./g if $attr->{pon_type} eq 'epon';  # Формат XXXX.XXXX.XXXX

Логування та відладка

ToLog - системне логування

ToLog(L('Запросив Detail Info ОНУ sn=[]', $attr->{sn}));
ToLog(L('Call rebootOnu [] sn=[]', $vendor, $sn));

debug - відладочне логування

debug('pre', $attr);           # Дамп змінної
debug $tc->last_prompt();      # Відладка prompt
debug "check onu";             # Простий текст

Створення БД таблиць для розширень

Приклад SQL схеми для Link Test:

CREATE TABLE IF NOT EXISTS `onu_link_test` (
  `id` int UNSIGNED NOT NULL AUTO_INCREMENT,
  `sn` varchar(32) NOT NULL,
  `tests` tinyint UNSIGNED NOT NULL,
  `result` tinyint UNSIGNED NOT NULL,
  `error` varchar(256) DEFAULT NULL,
  `admin` int UNSIGNED NOT NULL,
  `time` int UNSIGNED NOT NULL,
  PRIMARY KEY (`id`),
  KEY `sn` (`sn`)
) ENGINE=InnoDB COMMENT='ONU Link Tests';

Інтеграція з UI

Модальні вікна

# Для маленького вікна
ajSmall_window('a_onu_info', $content);

# Для модального вікна
if (ses::input_int('inmodal')) {
    unshift @$ses::cmd, {
        id   => 'modal_window',
        data => $content,
    };
}

Таблиці результатів

my $tbl = tbl->new(-class=>'td_wide pretty');
$tbl->add('*', [
    [ '', L('Час'), the_time($time) ],
    [ '', L('Результат'), $result ],
    [ '', L('Адмін'), $admin_id ],
]);
return $tbl->show;

Найкращі практики

1. Умовне відображення

  • Завжди перевіряйте вендора та модель
  • Використовуйте права доступу для критичних функцій

2. Безпека

  • Валідуйте всі вхідні дані
  • Використовуйте підтвердження для деструктивних операцій
  • Логуйте всі дії адміністраторів

3. Обробка помилок

  • Завжди закривайте Telnet з'єднання
  • Перевіряйте prompt'и перед виконанням команд
  • Повертайте зрозумілі повідомлення про помилки

4. Користувальницький досвід

  • Використовуйте локалізацію L()
  • Надавайте зворотний зв'язок про результат операцій
  • Створюйте форми для введення параметрів

Приклад повного patch-файлу

#<ACTION> file=>'web/ajOnuMenu.pl',hook=>'menu_bind', after=>['Ponmon']
        push @menuItems, { 
            order => 21, 
            title => L('Custom Action'), 
            act=>'customActionVendor' 
        } if lc($p{vendor}) =~ 'myvendor';

#<ACTION> file=>'web/ajOnuMenu.pl',hook=>'subs', after=>['Ponmon']

sub act_customActionVendor {
    my $attr = shift;
    
    # Форма підтвердження
    return $ajax_url->a($lang::btn_Execute, act=>'customActionVendor', go=>1) 
        unless ses::input_int('go');
    
    # Логування
    ToLog(L('Custom action for ONU sn=[]', $attr->{sn}));
    
    # Підключення до OLT
    my $tc = _telnetConnect($attr);
    return _tnError($tc, 'Connection failed') unless $tc;
    
    # Виконання команд
    my $result;
    if ($tc->last_prompt() =~ m/\#$/) {
        _tnCmd($tc, "show onu-info $attr->{sn}");
        $result = "Command executed successfully";
    } else {
        $result = "Error: Not in enable mode";
    }
    
    # Закриття з'єднання
    _telnetClose($tc);
    
    return $result;
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages