Обработчик активации сервисов для Mikrotik c изменениями скорости
Материал из BiTel WiKi
Изначально получен из скриптового шлюза IPN подобного этому: http://wiki.bgbilling.ru/index.php/%D0%A8%D0%BB%D1%8E%D0%B7_Mikrotik,_%D0%BE%D1%82%D1%80%D0%B0%D0%B1%D0%B0%D1%82%D1%8B%D0%B2%D0%B0%D1%8E%D1%89%D0%B8%D0%B9_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB_%D0%BD%D0%B0_%D0%B4%D0%BE%D0%B3%D0%BE%D0%B2%D0%BE%D1%80%D0%B5
Для поддержки макросов из команд шлюза IPN ( <LOOP></LOOP> и т.п) используется класс
InetDeviceCommandUtils . Сами команды заводятся в коде самого класса обработчика.
Код обработчика
package ru.gigacom.inet.dyn.device.mikrotik; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.log4j.Logger; import ru.bitel.bgbilling.common.BGException; import ru.bitel.bgbilling.modules.inet.access.sa.ServiceActivator; import ru.bitel.bgbilling.modules.inet.access.sa.ServiceActivatorAdapter; import ru.bitel.bgbilling.modules.inet.access.sa.ServiceActivatorEvent; import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDevice; import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDeviceType; import ru.bitel.bgbilling.modules.inet.api.common.bean.InetServ; import ru.bitel.bgbilling.modules.inet.api.server.bean.InetDeviceCommandUtils; import ru.bitel.bgbilling.modules.inet.runtime.InetOptionRuntime; import ru.bitel.bgbilling.modules.inet.runtime.InetOptionRuntimeMap; import ru.bitel.bgbilling.server.util.Setup; import ru.bitel.common.ParameterMap; import ru.bitel.common.inet.IpAddress; import bitel.billing.server.util.ssh.SSHSession; import bitel.billing.server.util.ssh.SSHSessionExec; public class MikrotikServiceActivator extends ServiceActivatorAdapter implements ServiceActivator { private static final Logger log = Logger.getLogger( MikrotikServiceActivator.class ); private static final String COMMANDS = "[DEFAULT]" + "[OPEN]" + ":global list \"\";" + ":foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] \"sid=serv_id;cid={CID};\"]=0) do={[/ip firewall address-list remove $i]}};" + ":global list \"\";" + ":foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] \"cid={CID};\"]=0) do={[/ip firewall address-list remove $i]}};" + //":foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i address] \"{A}\"]=0) do={[/ip firewall address-list remove $i]}};" + "<LOOP>" + "ip firewall address-list add address={A} list=ACCESS_LIST comment=\"sid=serv_id;cid={CID};rid=rule_id;\";" + "ip firewall address-list add address={A} list=${list_name} comment=\"sid=serv_id;cid={CID};rid=rule_id;\";" + "</LOOP>" + "[/OPEN]" + "[CLOSE]" + ":global list \"\";" + ":foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] \"sid=serv_id;cid={CID};\"]=0) do={[/ip firewall address-list remove $i]}};" + ":global list \"\";" + ":foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] \"cid={CID};\"]=0) do={[/ip firewall address-list remove $i]}};" + //":foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i address] \"{A}\"]=0) do={[/ip firewall address-list remove $i]}};" + "<LOOP>" + "ip firewall address-list add address={A} list=DENY_LIST comment=\"sid=serv_id;cid={CID};rid=rule_id;\";" + "</LOOP>" + "[/CLOSE]" + "[DELETE]" + ":global list \"\";" + ":foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] \"sid=serv_id;cid={CID};\"]=0) do={[/ip firewall address-list remove $i]}};" + ":global list \"\";" + ":foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i comment] \"cid={CID};\"]=0) do={[/ip firewall address-list remove $i]}};" + //":foreach i in [/ip firewall address-list find] do={:if ([:find [/ip firewall address-list get $i address] \"{A}\"]=0) do={[/ip firewall address-list remove $i]}};" + "[/DELETE]" + "[/DEFAULT]"; private static Pattern OPEN_PATTERN = Pattern.compile( "\\[OPEN\\](.*)\\[/OPEN\\]", Pattern.DOTALL ); private static Pattern CLOSE_PATTERN = Pattern.compile( "\\[CLOSE\\](.*)\\[/CLOSE\\]", Pattern.DOTALL ); private static Pattern DELETE_PATTERN = Pattern.compile( "\\[DELETE\\](.*)\\[/DELETE\\]", Pattern.DOTALL ); private SSHSession session = null; private InetDevice inetDevice; @Override public Object init( Setup setup, int moduleId, InetDevice inetDevice, InetDeviceType inetDeviceType, ParameterMap parameterMap ) throws Exception { this.inetDevice = inetDevice; //this.parameterMap = parameterMap; return true; } @Override public Object connect() throws Exception { List<InetSocketAddress> hosts = inetDevice.getHosts(); String host = hosts.get( 0 ).getHostName(); int port = hosts.get( 0 ).getPort(); String login = inetDevice.getUsername() + "+ct"; String pswd = inetDevice.getPassword(); if( log.isDebugEnabled() ) { log.debug( " gate: " + host + ":" + port + " login: " + login + " pswd: " + pswd ); } session = new SSHSession( host, port, login, pswd ); int timeout = 10000; session.setTimeout( timeout ); session.setEndString( " > " ); session.connect(); return true; } @Override public Object disconnect() throws Exception { session.doCommandAsync( "quit" ); session.disconnect(); log.debug( "ok" ); return true; } @Override public Object serviceModify( ServiceActivatorEvent serviceActivatorEvent ) throws Exception { InetServ serv = serviceActivatorEvent.getNewInetServ(); proccesServ( serviceActivatorEvent, serv ); return null; } private Object proccesServ( ServiceActivatorEvent serviceActivatorEvent, InetServ serv ) throws BGException, Exception { Set<Integer> oldOptions = serviceActivatorEvent.getOldOptions(); Set<Integer> newOptions = serviceActivatorEvent.getNewOptions(); log.debug( "oldState=" + serviceActivatorEvent.getOldState() + ";" + "newState=" + serviceActivatorEvent.getNewState() ); log.debug( "oldOptions=" + oldOptions + ";" + "newOptions=" + newOptions ); log.debug( "state!=state " + ( serviceActivatorEvent.getNewState() != serviceActivatorEvent.getOldState() ) ); if( serviceActivatorEvent.getNewState() != serviceActivatorEvent.getOldState() || !oldOptions.equals( newOptions ) ) { int state = serviceActivatorEvent.getNewState(); int servId = serviceActivatorEvent.getInetServId(); IpAddress addressFrom = new IpAddress( serv.getAddressFrom() ).clone(); IpAddress addressTo = new IpAddress( serv.getAddressTo() != null ? serv.getAddressTo() : serv.getAddressFrom() ).clone(); IpAddress current = addressFrom; List<String> ips = new ArrayList<String>(); log.info( "from =" + addressFrom.toString() ); log.info( "to =" + addressTo.toString() ); while ( current.compareTo( addressTo ) <= 0 ) { String ip = IpAddress.toString( current.address ); ips.add( ip ); log.info( ip ); log.info( "increment =" + IpAddress.increment( current.address ) ); } int cid = serv.getContractId(); int ruleId = 0; String optionConfig = ""; if( newOptions.size() > 0 ) { ruleId = (Integer)newOptions.toArray()[0]; InetOptionRuntime option = InetOptionRuntimeMap.getInstance().get( ruleId ); optionConfig = option.config.toString(); //listName = option.config.get( "list_name", "" ); //log.debug( "listName=" + listName ); log.debug( "optionConfig=" + optionConfig ); } //обход проблемы старта else { optionConfig="list_name=ACCESS_LIST"; } log.info( "cid=" + cid + ";rule_id=" + ruleId + ";" + "optionConfig=" + optionConfig ); String rules[] = null; if( state == InetServ.STATE_ENABLE ) { log.info( "open" ); // открываем rules = getRules( cid, servId, ruleId, ips, optionConfig, OPEN_PATTERN ); } else if( state == InetServ.STATE_DELETED ) { log.info( "detete" ); // удаляем rules = getRules( cid, servId, ruleId, ips, optionConfig, DELETE_PATTERN ); } else if( state == InetServ.STATE_DISABLE ) { // закрываем log.info( "close" ); rules = getRules( cid, servId, ruleId, ips, optionConfig, CLOSE_PATTERN ); } StringBuffer result = new StringBuffer(); log.debug( "rules.length=" + rules.length ); if( rules != null ) { for( String rule : rules ) { log.debug( "rule=" + rule ); result.append( session.doCommand( rule ) ); } log.debug( " result = " + result.toString() ); } } log.debug( "processed!" ); return null; } private String [] getRules( int cid, int serviceId, int ruleId, List<String> ips, String optionConfig, Pattern pattern ) { Map<String, String> replacements = new HashMap<String, String>(); replacements.put( "\\{CID\\}", String.valueOf( cid ) ); replacements.put( "rule_id", String.valueOf( ruleId ) ); replacements.put( "serv_id", String.valueOf( serviceId ) ); String result = InetDeviceCommandUtils.generateCommands( COMMANDS, pattern, ips, replacements, optionConfig ); result = result.replaceAll( "\r", "" ); //GateCommandUtil. return result.split( "\n" ); } @Override public Object serviceCreate( ServiceActivatorEvent e ) throws Exception { log.debug( "serviceCreate" ); return serviceModify( e ); } @Override public Object serviceCancel( ServiceActivatorEvent e ) throws Exception { log.debug( "serviceCancel" ); InetServ serv = e.getOldInetServ(); return proccesServ( e, serv ); } }