Реализация стандартного шлюза коммутатора Qtech/Zyxel (под Cisco2) на BeanShell со встроенным шлюзом DHCP
Материал из BiTel WiKi
После длительных раздумий вырисовалась связка Cisco2+(Zyxel/Qtech+DHCP) вместо предложенной разработчиками связки DHCP+Cisco2+Zyxel/Qtech. Данная связка нарисовалась в связи с тем, что некоторые параметры, которые нужно передать в шлюз DHCP, зависят от шлюза Zyxel/Qtech, а не от Cisco2, и получить к ним доступ в шлюзе DHCP не удалось. Т.е. шлюз Zyxel/Qtech совмещен с шлюзом DHCP. Суть состоит в том, что После синхронизации клиента на коммутаторе Zyxel, будет вызываться синхронизация с родительским шлюзом Cisco2, и синхронизация с сервером DHCP BgBilling'a. Все это написано для биллинга в.4.6 Ip адреса выдаются по влану клиента, т.к. в параметрах шлюза нельза менять vlan, а в сети может быть несколько одинаковых vlan находящихся в разных сегментах сети, принадлежащих одной сиске, влан клиента заносим в параметр договора. VLAN клиента уникальный в квартале. Можно выдавать ip адреса и по порту свича, что предпочтительней, но пока есть с этим у нас проблемы, поэтому и не используем. Конфигурация шлюза Cisco2:
#имя пользователя login=test #пароль шлюза который задаётся для enable cfg.pswd=123456 #диапазон выделения vlan range=1100-1900 #время ожидания ответа, по истечению которого, шлюз сбрасывает соединение и выдаёт ошибку timeout=2000 #код Vlan клиента параметра договора vlanId=1
Конфигурация типа шлюза Cisco2:
user_rule.editor.class=bitel.billing.module.services.ipn.editor.vlan.CiscoVlanContactRuleEditor #gate_manager.class=bitel.billing.server.ipn.vlan.CiscoVlanGateWorker #gate_manager.class=bitel.billing.server.ipn.DHCPGateWorker gate_manager.class=bitel.billing.server.ipn.vlan.CiscoVlanParentGateWorker use.script=1 #диапазон выделения vlan range=1100-1900
Команды шлюза Cisco2:
[DEFAULT] [REMOVE] <LOOP> no ip route {A} 255.255.255.255 Vlan{VID} </LOOP> [/REMOVE] [OPEN] <LOOP> ip route {A} 255.255.255.255 Vlan{VID} ip route {DHCP_Relay} 255.255.255.255 Vlan{VID} </LOOP> [/OPEN] [CLOSE] <LOOP> no ip route {A} 255.255.255.255 Vlan{VID} </LOOP> [/CLOSE] [/DEFAULT]
Скрипт шлюза Cisco2:
import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.StringTokenizer; import java.util.Map.Entry; import java.sql.*; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.Socket; import org.apache.xml.serializer.ToXMLStream; import org.xml.sax.SAXException; import bitel.billing.common.module.ipn.IPNContractStatus; import bitel.billing.server.ipn.GateWorker; import bitel.billing.server.ipn.UserStatus; import bitel.billing.server.ipn.bean.ManadUtils; import bitel.billing.server.ipn.bean.VlanManager; import bitel.billing.server.ipn.bean.GateType; import bitel.billing.server.ipn.bean.RuleType; import bitel.billing.server.ipn.bean.VlanManager; import bitel.billing.server.ipn.bean.Gate; import bitel.billing.server.util.DefaultServerSetup; import bitel.billing.server.util.Utils; import bitel.billing.server.util.telnet.TelnetSession; import ru.bitel.bgbilling.common.DefaultSetup; import bitel.billing.common.IPUtils; import ru.bitel.bgbilling.common.DefaultSetup; import bitel.billing.common.module.ipn.IPNContractStatus; import bitel.billing.server.ipn.dlink.UserPortStatus; import bitel.billing.server.ipn.dlink.UserPortStatus.UserPortStatusParser; /////protected void doSync() protected void parentSync( child, childWorker) { try { log.info( "start of cisco........................................................"); host = gate.getHost(); port = gate.getPort(); DefaultServerSetup gateSetup = new DefaultServerSetup( gate.getConfig(), "\r\n" ); pswdLogin = gate.getKeyword(); login = gateSetup.getStringValue( "login"); pswdCfg = gateSetup.getStringValue( "cfg.pswd"); timeout = gateSetup.getIntValue( "timeout", 0 ); vlanId = gateSetup.getIntValue( "vlanId",0); result = new StringBuffer(); if( log.isDebugEnabled() ) { log.debug( gate.getId() + " gate: " + host + ":" + port + " pswdLogin: " + pswdLogin + " pswdCfg: " + pswdCfg ); } session = new TelnetSession( host, port); session.setTimeout( timeout ); session.setLoginPromptSequence( ":" ); session.connect(); result.append( session.doCommand( login ) ); session.setLoginPromptSequence( ">" ); result.append( session.doCommand( pswdLogin ) ); result.append( session.doCommand( "terminal length 0" ) ); result.append( session.doCommand( "terminal width 0" ) ); session.setLoginPromptSequence( ":" ); result.append( session.doCommand( "enable" ) ); session.setLoginPromptSequence( "#" ); result.append( session.doCommand( pswdCfg ) ); result.append( session.doCommand( "configure terminal" ) ); // log.debug( "execute commands" ); // log.info( "------1------"); // log.info( "relayId = " + relayId); doCommands( session, result, child, vlanId); result.append( session.doCommand( "exit" ) ); session.doCommandAsync( "exit" ); // log.info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); log.info( result ); /* log.info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); log.debug( "ok" ); */ } catch (Exception e) { throw new RuntimeException ( e ); } log.info( "end of cisco........................................................"); } protected void add() { } /////private void doCommands( TelnetSession session, StringBuffer result, vlanId, relayId) throws IOException private void doCommands( TelnetSession session, StringBuffer result, Gate child, vlanId) throws IOException { for( UserStatus status : statusList ) { gateId = gate.getId(); // log.info("gateId=" + gateId); // log.info("vlanId=" + vlanId); // log.info("contractId=" + status.contractId); int vid_dog = getVlan( status.contractId, vlanId ); ///// Relay = getRelay( status.contractId, relayId ); DefaultServerSetup childSetup = new DefaultServerSetup( child.getConfig(), "\r\n" ); int vid = childSetup.getIntValue( "relay.vlan",1100); Relay = childSetup.getStringValue( "relay.ip","10.35.255.254"); // log.info("vid=" + vid); // log.info("Relay=" + Relay); //TODO - подумать что сделать справилами на добавление rules = null; if (status.status == IPNContractStatus.STATUS_OPEN) { rules = getOpenRules( status, vid, Relay, vid_dog); } // else if (status.status == IPNContractStatus.STATUS_REMOVED) // { // rules = getRemoveRules( status, vid ); // } //if closed and etc else { rules = getCloseRules( status, vid, Relay, vid_dog ); } if (vid > 0) { for ( String rule : rules ) { // log.info("rule=" + rule); result.append( session.doCommand( rule ) ); } } } } getOpenRules( status, vid, Relay, vid_dog ) { return getRules( status, "\\[OPEN\\](.*)\\[/OPEN\\]", vid, Relay, vid_dog ); } getCloseRules( status, vid, Relay, vid_dog ) { return getRules( status, "\\[CLOSE\\](.*)\\[/CLOSE\\]", vid, Relay, vid_dog ); } getRemoveRules( UserStatus status, int vid, Relay, vid_dog ) { return getRules( status, "\\[REMOVE\\](.*)\\[/REMOVE\\]", vid, Relay, vid_dog ); } getRules( status, template, vid, Relay, vid_dog ) { // пользовательское правило, без типа - то все оставляем как есть rule = status.rule.getRuleText(); // log.info("rule=" + rule); //порты идут до #, а адреса идут после String [] parts = rule.split( "#" ); portsStr = ""; addresesStr = ""; if ( parts.length > 0 ) { portsStr = parts[0]; } if ( parts.length > 1 ) { addresesStr = parts[1]; } //типизированное правило if( status.ruleType != null ) { rule = generateRule( addresesStr, status.gateType, status.ruleType, vid, Relay, vid_dog ); } // log.info("2rule=" + rule); pattern = Pattern.compile( template, Pattern.DOTALL ); m = pattern.matcher( rule ); if (m.find()) { rule = m.group( 1 ); } rule.replaceAll( "\r", "" ); parts = rule.split( "\n" ); result = new ArrayList(); for ( String part : parts ) { if ( !Utils.isEmptyString( part )) { result.add( part ); } } return result; } generateRule( addresses, gateType, ruleType, vid, Relay, vid_dog ) { // ruleText = ManadUtils.getRule( gateType, ruleType ); ruleText="[REMOVE]\n"+ "<LOOP>\n"+ "no ip route {A} 255.255.255.255 Vlan{VIDD}\n"+ "</LOOP>\n"+ "[/REMOVE]\n"+ "[OPEN]\n"+ "<LOOP>\n"+ "ip route {A} 255.255.255.255 Vlan{VIDD}\n"+ "ip route {DHCP_Relay} 255.255.255.255 Vlan{VID}\n"+ "</LOOP>\n"+ "[/OPEN]\n"+ "[CLOSE]\n"+ "<LOOP>\n"+ "no ip route {A} 255.255.255.255 Vlan{VIDD}\n"+ "</LOOP>\n"+ "[/CLOSE]\n"; log.info("ruleText = "+ruleText); replacements = new HashMap (); if (Relay != null || Relay.length()>0 ) { replacements.put( "\\{DHCP_Relay\\}", Relay ); } if ( vid_dog > 0) { replacements.put( "\\{VIDD\\}", String.valueOf( vid_dog ) ); } if ( vid > 0) { replacements.put( "\\{VID\\}", String.valueOf( vid ) ); } return ManadUtils.generateRule( ruleText, addresses, replacements, ruleType ); } getVlan( cid , pid ) { int result = 1102; String query = "select val from contract_parameter_type_1 where cid=" + cid + " and pid= " + pid; PreparedStatement ps = con.prepareStatement( query ); ResultSet rs = ps.executeQuery(); rs.first(); // log.info("Row = "+rs.getRow()); if ( rs. isFirst() ) { // log.info("---- First ------"); result = rs.getInt(1); } // log.info("Vlan = "+result); return result; }
У нас имеется 2 вида свичей Zyxel и Qtech, шлюзы у них одинаковые, только разные команды. Конфигурация шлюза Qtech: