forum.bitel.ru http://forum.bitel.ru/ |
|
Тип правила IPN (BGBS) http://forum.bitel.ru/viewtopic.php?f=19&t=2237 |
Страница 1 из 2 |
Автор: | lda [ 22 апр 2009, 17:26 ] |
Заголовок сообщения: | Тип правила IPN (BGBS) |
Ув. разработчики. Есть необходимость на BGBS вытащить тип правила (IPN) из текущего тарифа. Возможно ли это сделать используя API? Спасибо. |
Автор: | lda [ 23 апр 2009, 15:44 ] |
Заголовок сообщения: | |
Делаю автоматическое изменение скорости для IPN (Mikrotik). конфигурация типа шлюза : Код: user_rule.editor.class=bitel.billing.module.services.ipn.editor.MikrotikContractRuleEditor gate_manager.class=bitel.billing.server.ipn.MikrotikGateWorker use.script=1 Команды: Код: [DEFAULT] [OPEN] ip firewall address-list remove [find comment="!!{CID}!!"]; :global list ""; :foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] "cid={CID};"]=0) do={:set list ($list . "," . $i)}}; /ip firewall address-list remove $list; <LOOP> ip firewall address-list add address={A} list=ACCESS_LIST comment="cid={CID};rule_id;"; ip firewall address-list add address={A} list=${list_name} comment="cid={CID};rule_id;"; </LOOP> [/OPEN] [CLOSE] ip firewall address-list remove [find comment="!!{CID}!!"]; :global list ""; :foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] "cid={CID};"]=0) do={:set list ($list . "," . $i)}}; /ip firewall address-list remove $list; [/CLOSE] [DELETE] ip firewall address-list remove [find comment="!!{CID}!!"]; :global list ""; :foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] "cid={CID};"]=0) do={:set list ($list . "," . $i)}}; /ip firewall address-list remove $list; [/DELETE] [/DEFAULT] Пример типа правила: Код: list_name=Speed_Limit_1024 Скрипт: Код: import java.util.*;
import java.util.regex.*; import ru.bitel.bgbilling.common.*; import bitel.billing.common.module.ipn.*; import bitel.billing.server.ipn.bean.*; import bitel.billing.server.ipn.*; import bitel.billing.server.util.ssh.*; import bitel.billing.server.util.*; import bitel.billing.server.util.ssh.SSHSession; protected void doSync() { host = gate.getHost(); port = gate.getPort(); gateSetup = new DefaultServerSetup( gate.getConfig(), "\r\n" ); login = gateSetup.getStringValue( "login", "root" ); pswd = gate.getKeyword(); if ( log.isDebugEnabled() ) { log.debug( " gate: " + host + ":" + port + " login: " + login + " pswd: " + pswd ); } session = null; try { session = new SSHSessionExec( host, port, login, pswd ); address_list = session.command( "ip firewall address-list print without-paging" ); new_address_list = null; for ( UserStatus status : statusList ) { cid = status.contractId; ruleType = status.ruleType; rule_id = 0; if (ruleType != null) { rule_id = ruleType.getId(); }; rules = null; if (address_list.indexOf( "cid="+cid+";rule_id="+rule_id+";") != -1) { // правило для этого договора есть на шлюзе if ( status.status > 0 ) { if ( status.status == IPNContractStatus.STATUS_REMOVED ) { // удаляем rules = getDeleteRules( status ); } else { // закрываем rules = getCloseRules( status ); }; }; } else if ( status.status == IPNContractStatus.STATUS_OPEN ) { //открываем rules = getOpenRules( status ); }; if (rules != null){ for ( String rule : rules ) { p = Pattern.compile("rule_id"); m = p.matcher(rule); if (new_address_list == null) { new_address_list = ""; }; new_address_list = new_address_list + m.replaceAll("rule_id="+rule_id) + "\n"; }; }; } if (new_address_list != null){ print(address_list); print(new_address_list); result = session.command(new_address_list); print(result); }; } catch( Exception e ) { throw new RuntimeException( e ); } finally { if ( session != null ) { session.disconnect(); } } } private getOpenRules( status ) { return getRules( status, "\\[OPEN\\](.*)\\[/OPEN\\]" ); } private getCloseRules( status ) { return getRules( status, "\\[CLOSE\\](.*)\\[/CLOSE\\]" ); } private getDeleteRules( status ) { return getRules( status, "\\[DELETE\\](.*)\\[/DELETE\\]" ); } private getRules( status, template ) { // пользовательское правило, без типа - то все оставляем как есть rule = status.rule.getRuleText(); // типизированное правило if ( status.ruleType != null ) { rule = generateRule( rule, status.gateType, status.ruleType, status.contractId ); } pattern = Pattern.compile( template, Pattern.DOTALL ); m = pattern.matcher( rule ); if ( m.find() ) { rule = m.group( 1 ); } rule.replaceAll( "\r", "" ); return rule.split( "\n" ); } private generateRule( addresses, gateType, ruleType, cid ) { String rule; replacements = new HashMap(); replacements.put( "\\{CID\\}", String.valueOf( cid ) ); ruleText = ManadUtils.getRule( gateType, ruleType ); rule = ManadUtils.generateRule( ruleText, addresses, replacements, ruleType ); return rule; } Сейчас сие чудо меняет скорость на шлюзе, но только при изменении типа правила в договоре->Модули->IPN->Шлюзы->Управление шлюзом Хочу что бы тип правила брался напрямую из тарифа. Проблема со скоростью для IPN навилса давно и не только у меня. Помогите получить тип правила из тарифа. |
Автор: | Администратор [ 24 апр 2009, 10:18 ] |
Заголовок сообщения: | |
Скрин тарифа выложите, только все узлы чтобы раскрыты были. |
Автор: | vdd [ 24 апр 2009, 11:11 ] |
Заголовок сообщения: | |
lda писал(а): Хочу что бы тип правила брался напрямую из тарифа.
Проблема со скоростью для IPN навилса давно и не только у меня. Помогите получить тип правила из тарифа. Да, не только у lda нависла проблема со скоростью для IPN... |
Автор: | Администратор [ 24 апр 2009, 11:14 ] |
Заголовок сообщения: | |
Цитата: Но, необходим задел на будущее, скорость может меняться исходя из объема и времени суток. Следовательно необходима реализация через API.
Вам нужно получение скорости на текущий момент? |
Автор: | lda [ 24 апр 2009, 11:19 ] |
Заголовок сообщения: | |
Цитата: Вам нужно получение скорости на текущий момент?
Да. Хочу что бы при проверки шлюза мой скрипт получал текущий тип правила из тарифа. |
Автор: | lda [ 27 апр 2009, 15:18 ] |
Заголовок сообщения: | |
Код: import java.sql.*;
import java.util.*; import java.text.*; private ParseNode(node_id,H) { is_found = H.get("is_found"); if (is_found == null) { return; }; if (is_found) { return; }; sid = H.get("sid"); if (sid == null) { return; }; operation = H.get("operation"); if (operation == null) { return; }; time = H.get("time"); if (time == null) { return; }; query = "SELECT id, type, data FROM mtree_node WHERE parent_node='"+node_id+"'"; re = con.prepareStatement(query); ResultSet re = re.executeQuery(); while (re.next()) { id = re.getString(1); type = re.getString(2); data = re.getString(3); if (type.equals("service") && sid != Integer.parseInt(data)) { continue; }; if (type.equals("ipn_rule") && operation.equals("get_ipn_rule_id")) { datas = data.split ("&"); H.put("rule_id",datas[1]); H.put("is_found",true); }; if (type.equals("period")) { datas = data.split ("%"); date1 = null; date2 = null; for (i=0; i<datas.length; i++) { date_arr = datas[i].split("&"); if (date_arr.length != 2) { continue; }; formatter = new SimpleDateFormat("dd.MM.yyy"); date = formatter.parse(date_arr[1]); if (date_arr[0].equals("date1")) { date1 = date; }; if (date_arr[0].equals("date2")) { date2 = date; }; }; if (date1 != null && date1.compareTo(time.getTime()) != -1){ continue; }; if (date2 != null && date2.compareTo(time.getTime()) != 1){ continue; }; }; ParseNode(id,H); }; }; private ParseMTree(tree_id,H) { is_found = H.get("is_found"); if (is_found == null) { return; }; if (is_found) { return; }; mid = H.get("mid"); if (mid == null) { return; }; query = "SELECT mtree_node.id "+ "FROM module_tariff_tree "+ " INNER JOIN mtree_node "+ " ON (module_tariff_tree.id=mtree_node.mtree_id) "+ "WHERE mtree_node.type='root' AND module_tariff_tree.tree_id='"+tree_id+"' AND module_tariff_tree.mid='"+mid+"'"; re = con.prepareStatement(query); ResultSet re = re.executeQuery(); while (re.next()) { node_id = re.getString(1); ParseNode(node_id,H); }; } private ParseTarif(H) { H.put("is_found", false); cid = H.get("cid"); if (cid == null) { return; }; time = H.get("time"); if (time == null) { return; }; formatter = new SimpleDateFormat("yyyy-MM-dd"); tarif_date = formatter.format(time.getTime()).toString(); query = "SELECT contract_tree_link.tree_id "+ "FROM contract_tree_link "+ "WHERE "+ "(contract_tree_link.date1 is NULL OR contract_tree_link.date1<='"+tarif_date+"') AND "+ "(contract_tree_link.date2 is NULL OR contract_tree_link.date2>='"+tarif_date+"') AND "+ "contract_tree_link.cid='"+cid+"' "+ "UNION "+ "SELECT tariff_tree_link.tree_id "+ "FROM contract_tariff "+ " INNER JOIN tariff_tree_link "+ " ON (contract_tariff.tpid=tariff_tree_link.tpid) "+ "WHERE (contract_tariff.date1 is NULL OR contract_tariff.date1<='"+tarif_date+"') AND "+ "(contract_tariff.date2 is NULL OR contract_tariff.date2>='"+tarif_date+"') AND "+ "contract_tariff.cid='"+cid+"'"; re = con.prepareStatement(query); ResultSet re = re.executeQuery(); while (re.next()) { tree_id = re.getString(1); ParseMTree(tree_id,H); }; } private GetNowRule(){ H = new Hashtable(); H.put("operation", "get_ipn_rule_id"); H.put("cid", cid); H.put("mid", 4); H.put("sid", 5); H.put("time", new GregorianCalendar()); ParseTarif(H); rule_id = H.get("rule_id"); if (rule_id != null) { print("rile_id="+rule_id); event.addReport("rile_id="+rule_id+"\n"); }; } cid = event.getContractID(); GetNowRule(); Сделал пока вот такую заглушку, для получения текущего правила. В дереве тарифа обрабатывается пока только узел период. Мне пока другое и не требуется. При необходимости доделаю... Ув. разработчики, надуюсь, что в перспективе вы реализуете необходимый функционал в API. |
Автор: | stark [ 27 апр 2009, 16:43 ] |
Заголовок сообщения: | |
Это возможно будет отдельная задача простановки статусов тогда , не обязательно совмещання с задачай проверки шлюзов .. Есть правда такой момент - если вам потребуется получить скорость в текущий момент в зависимости от наработки , а наработки еще нет, то не всегда будет ставить правило правильно |
Автор: | lda [ 27 апр 2009, 17:08 ] |
Заголовок сообщения: | |
Цитата: Это возможно будет отдельная задача простановки статусов тогда , не обязательно совмещання с задачай проверки шлюзов На мой взгляд особо менять ничего не надо. Есть начисление, которое обрабатывает данные и считает услугу согласно тарифу. Есть управление шлюзом, которое получает скорость из тарифа и делает необходимые изменения на шлюзе. Цитата: Есть правда такой момент - если вам потребуется получить скорость в текущий момент в зависимости от наработки , а наработки еще нет, то не всегда будет ставить правило правильно
А как решается вопрос с тем что клиент может уйти в глубокий минус, потому что данные о наработке приходят с задержкой? Никак он не решается..., спицифика работы IPN такая... В последнее время безлимитные тарифы используются все чаще и чаще, так что я думаю что не стоит заморачиваться с такими вещами. |
Автор: | stark [ 27 апр 2009, 18:00 ] |
Заголовок сообщения: | |
lda писал(а): Цитата: Это возможно будет отдельная задача простановки статусов тогда , не обязательно совмещання с задачай проверки шлюзов На мой взгляд особо менять ничего не надо. Есть начисление, которое обрабатывает данные и считает услугу согласно тарифу. Есть управление шлюзом, которое получает скорость из тарифа и делает необходимые изменения на шлюзе. я просто хотел внести еще одно изменение , т.е вынести это из задачи проверки шлюзов ..В идиале задача проверки шлюзов просто проверяет соотвестует ли стаус шлюза статусу в бд биллинга и все ..но сейчас она еще и сам стаус в бд меняет - если денег нет.. а еще будет правило искать в тарифе и менять его в бд для текущуего шлюза ..надо это хотя бы убрать , т.к как миниму половине пользователей смена скорости не нужна (хотя конечно это можно и опцией отключить по умолчанию ) lda писал(а): Цитата: Есть правда такой момент - если вам потребуется получить скорость в текущий момент в зависимости от наработки , а наработки еще нет, то не всегда будет ставить правило правильно А как решается вопрос с тем что клиент может уйти в глубокий минус, потому что данные о наработке приходят с задержкой? Никак он не решается..., спицифика работы IPN такая... В последнее время безлимитные тарифы используются все чаще и чаще, так что я думаю что не стоит заморачиваться с такими вещами. ну, да специфика такая .. надо либо убрать возможность добавлять типы правил в узлы с наработкой (или в их потомков ) , либо потом объяснять всем что это не работает и почему.. Ну, в принципе можно сделать ..добавил в TODO |
Автор: | lda [ 27 апр 2009, 18:31 ] |
Заголовок сообщения: | |
Цитата: но сейчас она еще и сам стаус в бд меняет - если денег нет Если текущий баланс < лимита, то статус шлюза меняется на "Заблокирован". Какой процесс это делает, проверка шлюзов или начисление? Я так понял что проверка шлюзов. Будет ли меняться статус шлюза при использовании моего скрипта, или мне необходимо предусмотреть это в коде? Цитата: как миниму половине пользователей смена скорости не нужна Я в этом не уверен. Скорость может меняться не из за специфики тарифа, а просто при изменении тарифного плана. Я думаю что большинство из нас предоставляет безлимитные тарифы физическим лицам, а они время от времени тарифы все таки меняют. И сидеть ночью и менять скорость у пользователей, открывать и закрывать шлюз, вручную перспектива не завидная... Можете провести голосование, что бы не ошибиться с выбором Цитата: ну, да специфика такая .. надо либо убрать возможность добавлять типы правил в узлы с наработкой (или в их потомков ) , либо потом объяснять всем что это не работает и почему.. Ну, в принципе можно сделать ..добавил в TODO
Думаю, что возможность менять скорость в зависимости от наработки, времени суток и т.д. все таки нужна, так же как и в модуле Dialup. Может быть стоит подумать как уменьшить задержку попадания наработки? |
Автор: | lda [ 28 апр 2009, 17:05 ] |
Заголовок сообщения: | |
Вот окончательный вариант скрипта для Mikrotik, который меняет скорость на шлюзе, а тип правила берет из тарифа, для тех кому интересно: Код: import java.util.*;
import java.util.regex.*; import java.text.*; import java.sql.*; import ru.bitel.bgbilling.common.*; import bitel.billing.common.module.ipn.*; import bitel.billing.server.ipn.bean.*; import bitel.billing.server.ipn.*; import bitel.billing.server.util.ssh.*; import bitel.billing.server.util.*; import bitel.billing.server.util.ssh.SSHSession; protected void doSync() { host = gate.getHost(); port = gate.getPort(); gateSetup = new DefaultServerSetup( gate.getConfig(), "\r\n" ); login = gateSetup.getStringValue( "login", "root" ); pswd = gate.getKeyword(); if ( log.isDebugEnabled() ) { log.debug( " gate: " + host + ":" + port + " login: " + login + " pswd: " + pswd ); } session = null; try { session = new SSHSessionExec( host, port, login, pswd ); address_list = session.command( "ip firewall address-list print without-paging" ); for ( UserStatus status : statusList ) { new_address_list = null; cid = status.contractId; getNewRule(status); ruleType = status.ruleType; rule_id = 0; if (ruleType != null) { rule_id = ruleType.getId(); }; rules = null; if (address_list.indexOf( "cid="+cid+";rule_id="+rule_id+";") != -1) { // правило для этого договора есть на шлюзе if ( status.status > 0 ) { if ( status.status == IPNContractStatus.STATUS_REMOVED ) { // удаляем rules = getDeleteRules( status ); log.info("DeleteRules cid="+cid+" rule_id="+rule_id); } else { // закрываем rules = getCloseRules( status ); log.info("CloseRules cid="+cid+" rule_id="+rule_id); }; }; } else if ( status.status == IPNContractStatus.STATUS_OPEN ) { //открываем rules = getOpenRules( status ); log.info("OpenRules cid="+cid+" rule_id="+rule_id); }; if (rules != null) { for ( String rule : rules ) { p = Pattern.compile("rule_id"); m = p.matcher(rule); if (new_address_list == null) { new_address_list = ""; }; new_address_list = new_address_list + m.replaceAll("rule_id="+rule_id) + "\n"; }; }; if (new_address_list != null){ // print(address_list); // print(new_address_list); result = session.command(new_address_list); // print(result); }; }; } catch( Exception e ) { throw new RuntimeException( e ); } finally { if ( session != null ) { session.disconnect(); } } } private getOpenRules( status ) { return getRules( status, "\\[OPEN\\](.*)\\[/OPEN\\]" ); } private getCloseRules( status ) { return getRules( status, "\\[CLOSE\\](.*)\\[/CLOSE\\]" ); } private getDeleteRules( status ) { return getRules( status, "\\[DELETE\\](.*)\\[/DELETE\\]" ); } private getRules( status, template ) { // пользовательское правило, без типа - то все оставляем как есть rule = status.rule.getRuleText(); // типизированное правило if ( status.ruleType != null ) { rule = generateRule( rule, status.gateType, status.ruleType, status.contractId ); } pattern = Pattern.compile( template, Pattern.DOTALL ); m = pattern.matcher( rule ); if ( m.find() ) { rule = m.group( 1 ); } rule.replaceAll( "\r", "" ); return rule.split( "\n" ); } private generateRule( addresses, gateType, ruleType, cid ) { String rule; replacements = new HashMap(); replacements.put( "\\{CID\\}", String.valueOf( cid ) ); ruleText = ManadUtils.getRule( gateType, ruleType ); rule = ManadUtils.generateRule( ruleText, addresses, replacements, ruleType ); return rule; } private getNewRule(status) { if (status.ruleType == null){ return; }; H = new Hashtable(); H.put("operation", "get_ipn_rule_id"); H.put("cid", status.contractId); H.put("mid", status.mid); H.put("sid", 5); H.put("time", new GregorianCalendar()); ParseTarif(H); rule_id = H.get("rule_id"); if (rule_id != null) { rule_type_manager = new RuleTypeManager(con,status.mid); status.ruleType = rule_type_manager.getType(Integer.parseInt(rule_id)); }; } private ParseTarif(H) { H.put("is_found", false); cid = H.get("cid"); if (cid == null) { return; }; time = H.get("time"); if (time == null) { return; }; formatter = new SimpleDateFormat("yyyy-MM-dd"); tarif_date = formatter.format(time.getTime()).toString(); query = "SELECT contract_tree_link.tree_id "+ "FROM contract_tree_link "+ "WHERE "+ "(contract_tree_link.date1 is NULL OR contract_tree_link.date1<='"+tarif_date+"') AND "+ "(contract_tree_link.date2 is NULL OR contract_tree_link.date2>='"+tarif_date+"') AND "+ "contract_tree_link.cid='"+cid+"' "+ "UNION "+ "SELECT tariff_tree_link.tree_id "+ "FROM contract_tariff "+ " INNER JOIN tariff_tree_link "+ " ON (contract_tariff.tpid=tariff_tree_link.tpid) "+ "WHERE (contract_tariff.date1 is NULL OR contract_tariff.date1<='"+tarif_date+"') AND "+ "(contract_tariff.date2 is NULL OR contract_tariff.date2>='"+tarif_date+"') AND "+ "contract_tariff.cid='"+cid+"'"; re = con.prepareStatement(query); rs = re.executeQuery(); while (rs.next()) { tree_id = rs.getString(1); ParseMTree(tree_id,H); }; } private ParseMTree(tree_id,H) { is_found = H.get("is_found"); if (is_found == null) { return; }; if (is_found) { return; }; mid = H.get("mid"); if (mid == null) { return; }; query = "SELECT mtree_node.id "+ "FROM module_tariff_tree "+ " INNER JOIN mtree_node "+ " ON (module_tariff_tree.id=mtree_node.mtree_id) "+ "WHERE mtree_node.type='root' AND module_tariff_tree.tree_id='"+tree_id+"' AND module_tariff_tree.mid='"+mid+"'"; re = con.prepareStatement(query); rs = re.executeQuery(); while (rs.next()) { node_id = rs.getString(1); ParseNode(node_id,H); }; } private ParseNode(node_id,H) { is_found = H.get("is_found"); if (is_found == null) { return; }; if (is_found) { return; }; sid = H.get("sid"); if (sid == null) { return; }; operation = H.get("operation"); if (operation == null) { return; }; time = H.get("time"); if (time == null) { return; }; query = "SELECT id, type, data FROM mtree_node WHERE parent_node='"+node_id+"'"; re = con.prepareStatement(query); rs = re.executeQuery(); while (rs.next()) { id = rs.getString(1); type = rs.getString(2); data = rs.getString(3); if (type.equals("service") && sid != Integer.parseInt(data)) { continue; }; if (type.equals("ipn_rule") && operation.equals("get_ipn_rule_id")) { datas = data.split ("&"); H.put("rule_id",datas[1]); H.put("is_found",true); }; if (type.equals("period")) { datas = data.split ("%"); date1 = null; date2 = null; for (i=0; i<datas.length; i++) { date_arr = datas[i].split("&"); if (date_arr.length != 2) { continue; }; formatter = new SimpleDateFormat("dd.MM.yyy"); date = formatter.parse(date_arr[1]); if (date_arr[0].equals("date1")) { date1 = date; }; if (date_arr[0].equals("date2")) { date2 = date; }; }; if (date1 != null && date1.compareTo(time.getTime()) != -1){ continue; }; if (date2 != null && date2.compareTo(time.getTime()) != 1){ continue; }; }; ParseNode(id,H); }; }; |
Автор: | mikos [ 08 июл 2009, 03:01 ] |
Заголовок сообщения: | |
lda, подскажите пожалуйста, почему могут не удаляться списки в вашем скрипте при блокировании и удалении шлюза? Кстати, каким образом режете скорость с помощью списков каждому абоненту персонально? |
Автор: | lda [ 08 июл 2009, 10:32 ] |
Заголовок сообщения: | |
mikos писал(а): lda, подскажите пожалуйста, почему могут не удаляться списки в вашем скрипте при блокировании и удалении шлюза? Кстати, каким образом режете скорость с помощью списков каждому абоненту персонально?
Для начала замечу что строчка: Код: ip firewall address-list remove [find comment="!!{CID}!!"]; это пережиток прошлого, уберите ее. Правила мы удаляем так: Код: :global list "";
:foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] "cid={CID};"]=0) do={:set list ($list . "," . $i)}}; /ip firewall address-list remove $list; попробуйте вручную выполнить эту команду, я с ней тоже долго возился Скорость мы режем access листами, т.е для открытого шлюза IP добавлен в ACCESS_LIST и в ACCESS_LIST_{скорость}, а для закрытого шлюза IP удален изо всех access листов. |
Автор: | mikos [ 08 июл 2009, 12:31 ] |
Заголовок сообщения: | |
Сейчас попробую поиграться с этой строчкой, спасибо. А вот с ACCESS_LIST_{скорость} не понял. Я сначала предполагал создавать каждому по queue simple, но с acl было бы интересней. Подскажите пожалуйста, каким образом используете acl для нарезки скорости? |
Автор: | lda [ 08 июл 2009, 14:39 ] |
Заголовок сообщения: | |
Цитата: Подскажите пожалуйста, каким образом используете acl для нарезки скорости?
Вот так мы добавляем Speed_Limit_10240 для абонентов, у которых должна быть скорость 10240000. Что тут что я подсказать к сожалению не смогу, я занимаюсь обслуживанием биллинга, а не микротика. Код: /queue type
add kind=pcq name=unlim_10240_upload pcq-classifier=src-address pcq-limit=400 pcq-rate=10240000 \ pcq-total-limit=40000 add kind=pcq name=unlim_10240_download pcq-classifier=dst-address pcq-limit=400 pcq-rate=10240000 \ pcq-total-limit=40000 /queue tree add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 name=unlim_10240_download packet-mark=unlim_10240_download parent=global-in priority=8 queue=unlim_10240_download add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 name=unlim_10240_upload packet-mark=unlim_10240_upload parent=global-out priority=8 queue=unlim_10240_upload /ip firewall mangle add action=mark-packet chain=prerouting comment=Speed_Limit_10240 disabled=no new-packet-mark=unlim_10240_upload passthrough=no src-address-list=Speed_Limit_10240 add action=mark-packet chain=prerouting comment="" disabled=no dst-address-list=Speed_Limit_10240 new-packet-mark=unlim_10240_download passthrough=no |
Автор: | mikos [ 08 июл 2009, 17:33 ] |
Заголовок сообщения: | |
Спасибо. Т.е. таким способом Вы режете КАЖДОМУ по той скорости что в группе? По поводу невозможности удалить скриптом правила со шлюза. Порасставлял дебаги в скрипте, да попробовал выполнить кусок на микротике. Интересная вещь. 1. Код который должен выполняться на микротике, с консоли микротика отрабатывает на ура - удаляет во всех списках 2. Код со шлюза выходит вроде в том виде, что надо, но не отрабатывает и выдает такую ошибку на вот такой код: Кусок кода, который отслеживал Код: if (rules != null) { for ( String rule : rules ) { p = Pattern.compile("rule_id"); m = p.matcher(rule); if (new_address_list == null) { new_address_list = ""; }; new_address_list = new_address_list + m.replaceAll("rule_id="+rule_id) + "\n"; }; }; if (new_address_list != null){ print("Address LIST:\n"); print(address_list); print("NEW Address LIST:\n"); print(new_address_list); result = session.command(new_address_list); print("RESULT:\n"); print(result); }; И вот что на этот кусок получаю в дебаге Код: NEW Address LIST: :global list ""; :foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] "cid=34;"]=0) do={:set list ($list . "," . $i)}}; /ip firewall address-list remove $list; /queue simple remove [find comment="cid=34"]; RESULT: expected variable name (line 2 column 131) syntax error (line 2 column 35) Беру прямо с экрана копиру в консоль микротика и код отрабатывает Код: :global list "";
:foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] "cid=34;"]=0) do={:set list ($list . "," . $i)}}; /ip firewall address-list remove $list; /queue simple remove [find comment="cid=34"]; Как думаете, что может быть не так? |
Автор: | lda [ 08 июл 2009, 17:56 ] |
Заголовок сообщения: | |
Цитата: Как думаете, что может быть не так?
Когда делал сам, то тоже была такая проблема, что в консоле удалялись правила а через биллинг нет. Я вроде бы убирал там лишнюю точку с запятой, и после этого все заработало. Может быть у нас разные версии микротика... |
Автор: | mikos [ 08 июл 2009, 18:11 ] |
Заголовок сообщения: | |
У меня версия 3.20 А на форуме текущий ваш рабочий вариант опубликован или Вы что-то допиливали еще? Пожет как раз тот, где была ошибка? |
Автор: | lda [ 08 июл 2009, 18:19 ] |
Заголовок сообщения: | |
а у нас 3.22. Вот данные прямо из биллинга: Код: [DEFAULT] [OPEN] ip firewall address-list remove [find comment="!!{CID}!!"]; :global list ""; :foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] "cid={CID};"]=0) do={:set list ($list . "," . $i)}}; /ip firewall address-list remove $list; <LOOP> ip firewall address-list add address={A} list=ACCESS_LIST comment="cid={CID};rule_id;"; ip firewall address-list add address={A} list=${list_name} comment="cid={CID};rule_id;"; </LOOP> [/OPEN] [CLOSE] ip firewall address-list remove [find comment="!!{CID}!!"]; :global list ""; :foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] "cid={CID};"]=0) do={:set list ($list . "," . $i)}}; /ip firewall address-list remove $list; [/CLOSE] [DELETE] ip firewall address-list remove [find comment="!!{CID}!!"]; :global list ""; :foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] "cid={CID};"]=0) do={:set list ($list . "," . $i)}}; /ip firewall address-list remove $list; [/DELETE] [/DEFAULT] Код: import java.util.*;
import java.util.regex.*; import java.text.*; import java.sql.*; import ru.bitel.bgbilling.common.*; import bitel.billing.common.module.ipn.*; import bitel.billing.server.ipn.bean.*; import bitel.billing.server.ipn.*; import bitel.billing.server.util.ssh.*; import bitel.billing.server.util.*; import bitel.billing.server.util.ssh.SSHSession; protected void doSync() { host = gate.getHost(); port = gate.getPort(); gateSetup = new DefaultServerSetup( gate.getConfig(), "\r\n" ); login = gateSetup.getStringValue( "login", "root" ); pswd = gate.getKeyword(); if ( log.isDebugEnabled() ) { log.debug( " gate: " + host + ":" + port + " login: " + login + " pswd: " + pswd ); } session = null; try { session = new SSHSessionExec( host, port, login, pswd ); address_list = session.command( "ip firewall address-list print without-paging" ); for ( UserStatus status : statusList ) { new_address_list = null; cid = status.contractId; getNewRule(status); ruleType = status.ruleType; rule_id = 0; if (ruleType != null) { rule_id = ruleType.getId(); }; rules = null; if (address_list.indexOf( "cid="+cid+";rule_id="+rule_id+";") != -1) { // правило для этого договора есть на шлюзе if ( status.status > 0 ) { if ( status.status == IPNContractStatus.STATUS_REMOVED ) { // удаляем rules = getDeleteRules( status ); log.info("DeleteRules cid="+cid+" rule_id="+rule_id); } else { // закрываем rules = getCloseRules( status ); log.info("CloseRules cid="+cid+" rule_id="+rule_id); }; }; } else if ( status.status == IPNContractStatus.STATUS_OPEN ) { //открываем rules = getOpenRules( status ); log.info("OpenRules cid="+cid+" rule_id="+rule_id); }; if (rules != null) { for ( String rule : rules ) { p = Pattern.compile("rule_id"); m = p.matcher(rule); if (new_address_list == null) { new_address_list = ""; }; new_address_list = new_address_list + m.replaceAll("rule_id="+rule_id) + "\n"; }; }; if (new_address_list != null){ // print(address_list); // print(new_address_list); result = session.command(new_address_list); // print(result); }; }; } catch( Exception e ) { throw new RuntimeException( e ); } finally { if ( session != null ) { session.disconnect(); } } } private getOpenRules( status ) { return getRules( status, "\\[OPEN\\](.*)\\[/OPEN\\]" ); } private getCloseRules( status ) { return getRules( status, "\\[CLOSE\\](.*)\\[/CLOSE\\]" ); } private getDeleteRules( status ) { return getRules( status, "\\[DELETE\\](.*)\\[/DELETE\\]" ); } private getRules( status, template ) { // пользовательское правило, без типа - то все оставляем как есть rule = status.rule.getRuleText(); // типизированное правило if ( status.ruleType != null ) { rule = generateRule( rule, status.gateType, status.ruleType, status.contractId ); } pattern = Pattern.compile( template, Pattern.DOTALL ); m = pattern.matcher( rule ); if ( m.find() ) { rule = m.group( 1 ); } rule.replaceAll( "\r", "" ); return rule.split( "\n" ); } private generateRule( addresses, gateType, ruleType, cid ) { String rule; replacements = new HashMap(); replacements.put( "\\{CID\\}", String.valueOf( cid ) ); ruleText = ManadUtils.getRule( gateType, ruleType ); rule = ManadUtils.generateRule( ruleText, addresses, replacements, ruleType ); return rule; } private getNewRule(status) { if (status.ruleType == null){ return; }; H = new Hashtable(); H.put("operation", "get_ipn_rule_id"); H.put("cid", status.contractId); H.put("mid", status.mid); H.put("sid", 5); H.put("time", new GregorianCalendar()); ParseTarif(H); rule_id = H.get("rule_id"); if (rule_id != null) { rule_type_manager = new RuleTypeManager(con,status.mid); status.ruleType = rule_type_manager.getType(Integer.parseInt(rule_id)); }; } private ParseTarif(H) { H.put("is_found", false); cid = H.get("cid"); if (cid == null) { return; }; time = H.get("time"); if (time == null) { return; }; formatter = new SimpleDateFormat("yyyy-MM-dd"); tarif_date = formatter.format(time.getTime()).toString(); query = "SELECT contract_tree_link.tree_id "+ "FROM contract_tree_link "+ "WHERE "+ "(contract_tree_link.date1 is NULL OR contract_tree_link.date1<='"+tarif_date+"') AND "+ "(contract_tree_link.date2 is NULL OR contract_tree_link.date2>='"+tarif_date+"') AND "+ "contract_tree_link.cid='"+cid+"' "+ "UNION "+ "SELECT tariff_tree_link.tree_id "+ "FROM contract_tariff "+ " INNER JOIN tariff_tree_link "+ " ON (contract_tariff.tpid=tariff_tree_link.tpid) "+ "WHERE (contract_tariff.date1 is NULL OR contract_tariff.date1<='"+tarif_date+"') AND "+ "(contract_tariff.date2 is NULL OR contract_tariff.date2>='"+tarif_date+"') AND "+ "contract_tariff.cid='"+cid+"'"; re = con.prepareStatement(query); rs = re.executeQuery(); while (rs.next()) { tree_id = rs.getString(1); ParseMTree(tree_id,H); }; } private ParseMTree(tree_id,H) { is_found = H.get("is_found"); if (is_found == null) { return; }; if (is_found) { return; }; mid = H.get("mid"); if (mid == null) { return; }; query = "SELECT mtree_node.id "+ "FROM module_tariff_tree "+ " INNER JOIN mtree_node "+ " ON (module_tariff_tree.id=mtree_node.mtree_id) "+ "WHERE mtree_node.type='root' AND module_tariff_tree.tree_id='"+tree_id+"' AND module_tariff_tree.mid='"+mid+"'"; re = con.prepareStatement(query); rs = re.executeQuery(); while (rs.next()) { node_id = rs.getString(1); ParseNode(node_id,H); }; } private ParseNode(node_id,H) { is_found = H.get("is_found"); if (is_found == null) { return; }; if (is_found) { return; }; sid = H.get("sid"); if (sid == null) { return; }; operation = H.get("operation"); if (operation == null) { return; }; time = H.get("time"); if (time == null) { return; }; query = "SELECT id, type, data FROM mtree_node WHERE parent_node='"+node_id+"'"; re = con.prepareStatement(query); rs = re.executeQuery(); while (rs.next()) { id = rs.getString(1); type = rs.getString(2); data = rs.getString(3); if (type.equals("service") && sid != Integer.parseInt(data)) { continue; }; if (type.equals("ipn_rule") && operation.equals("get_ipn_rule_id")) { datas = data.split ("&"); H.put("rule_id",datas[1]); H.put("is_found",true); }; if (type.equals("period")) { datas = data.split ("%"); date1 = null; date2 = null; for (i=0; i<datas.length; i++) { date_arr = datas[i].split("&"); if (date_arr.length != 2) { continue; }; formatter = new SimpleDateFormat("dd.MM.yyyy"); date = formatter.parse(date_arr[1]); if (date_arr[0].equals("date1")) { date1 = date; }; if (date_arr[0].equals("date2")) { date2 = date; }; }; if (date1 != null && date1.compareTo(time.getTime()) != -1){ continue; }; if (date2 != null && date2.compareTo(time.getTime()) != 1){ continue; }; }; ParseNode(id,H); }; }; Я уже не найду старый вариант, да и времени нет сейчас разбираться... Посмотрите документацию по микротику. |
Автор: | mikos [ 08 июл 2009, 18:25 ] |
Заголовок сообщения: | |
Спасибо, буду ковырять. |
Автор: | mikos [ 09 июл 2009, 03:20 ] |
Заголовок сообщения: | |
lda писал(а): Цитата: Подскажите пожалуйста, каким образом используете acl для нарезки скорости? Вот так мы добавляем Speed_Limit_10240 для абонентов, у которых должна быть скорость 10240000. Что тут что я подсказать к сожалению не смогу, я занимаюсь обслуживанием биллинга, а не микротика. Код: /queue type add kind=pcq name=unlim_10240_upload pcq-classifier=src-address pcq-limit=400 pcq-rate=10240000 \ pcq-total-limit=40000 add kind=pcq name=unlim_10240_download pcq-classifier=dst-address pcq-limit=400 pcq-rate=10240000 \ pcq-total-limit=40000 /queue tree add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 name=unlim_10240_download packet-mark=unlim_10240_download parent=global-in priority=8 queue=unlim_10240_download add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 name=unlim_10240_upload packet-mark=unlim_10240_upload parent=global-out priority=8 queue=unlim_10240_upload /ip firewall mangle add action=mark-packet chain=prerouting comment=Speed_Limit_10240 disabled=no new-packet-mark=unlim_10240_upload passthrough=no src-address-list=Speed_Limit_10240 add action=mark-packet chain=prerouting comment="" disabled=no dst-address-list=Speed_Limit_10240 new-packet-mark=unlim_10240_download passthrough=no Переписал таки скрипт, сейчас все удаляется как надо. Проблема похоже была в том, что у вас была определена глобальная переменная и сразу проинициализирована пустой строкой. У меня не принимал микротик такую конструкцию. По поводу нарезки скорости. Вы похоже без NAT на микротике работаете, раз режете таким образом? Нарезка таким образом с использованием NAT не получится, т.к. пометить входящий трафик не получится ибо NAT работает после цепочки postrouting |
Автор: | Dog [ 08 ноя 2009, 20:41 ] |
Заголовок сообщения: | Re: Тип правила IPN (BGBS) |
Добрый день, а не мог бы кто нибудь, использующий этот скрипт для микротика, выложить сдесь пример своего тарифа. |
Автор: | Dog [ 09 ноя 2009, 17:20 ] | ||
Заголовок сообщения: | Re: Тип правила IPN (BGBS) | ||
Добрый день, суть проблемы в том, что например при следующем виде тарифа (см. приложение) cкрипт не меняет скорость абоненту если он исчерпал лимит. Хотя если зайти в закладку Шлюзы договора с этим тарифом, то правило меняется.
|
Автор: | mikos [ 09 ноя 2009, 18:42 ] |
Заголовок сообщения: | Re: Тип правила IPN (BGBS) |
Dog писал(а): Добрый день, суть проблемы в том, что например при следующем виде тарифа (см. приложение) cкрипт не меняет скорость абоненту если он исчерпал лимит. Хотя если зайти в закладку Шлюзы договора с этим тарифом, то правило меняется. А задача "Проверка шлюзов IPN" проходит? В логах ошибок нет? |
Автор: | Dog [ 14 ноя 2009, 12:09 ] |
Заголовок сообщения: | Re: Тип правила IPN (BGBS) |
mikos писал(а): А задача "Проверка шлюзов IPN" проходит? В логах ошибок нет? задача проходит, в логах тишина. Если например руками менять тариф, или правило в тарифе, то на микротике speed list меняется. |
Автор: | lda [ 16 ноя 2009, 12:46 ] |
Заголовок сообщения: | Re: Тип правила IPN (BGBS) |
Ув. Dog это скрипт не рассчитан на такой тариф. Вам необходимо переписать функцию ParseNode. |
Автор: | Dog [ 02 фев 2010, 13:14 ] |
Заголовок сообщения: | Re: Тип правила IPN (BGBS) |
Удалось ли кому-нибудь реализовать «псевдо» безлимитный тарифный план на шлюзах Mikrotik? Большая просьба поделиться опытом. |
Автор: | madmax [ 08 фев 2010, 21:52 ] |
Заголовок сообщения: | Re: Тип правила IPN (BGBS) |
А что делиться опытом. Создаешь Типы правил, привязываешь их в тариф и все, далее задача проверки шлюзов проверяет тип правила и меняет его на действующий. |
Страница 1 из 2 | Часовой пояс: UTC + 5 часов [ Летнее время ] |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |