forum.bitel.ru http://forum.bitel.ru/ |
|
Mikrotik API Client http://forum.bitel.ru/viewtopic.php?f=7&t=5328 |
Страница 1 из 1 |
Автор: | akubik [ 01 апр 2011, 18:10 ] |
Заголовок сообщения: | Mikrotik API Client |
Вывожу свои скрипты для работы с микротиком через API. Библиотека mikrotik. Оригинальный автор классов - некто Яниск, я же переделал их на BeanShell и добавил пару классов для удобства. Код: import java.io.*; import java.net.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; import java.util.logging.Logger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays.copyOf; /** * * @orginal author janisk */ public class Hasher { /** * makes MD5 hash of string for use with RouterOS API * @param s - variable to make hacsh from * @return */ static public String hashMD5(String s) { String md5val = ""; MessageDigest algorithm = null; int i; try { algorithm = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException nsae) { System.out.println("Cannot find digest algorithm"); System.exit(1); } byte[] defaultBytes = new byte[s.length()]; for (i = 0; i < s.length(); i++) { defaultBytes[i] = (byte) (0xFF & s.charAt(i)); } algorithm.reset(); algorithm.update(defaultBytes); messageDigest = algorithm.digest(); StringBuffer hexString = new StringBuffer(); for (i = 0; i < messageDigest.length; i++) { String hex = Integer.toHexString(0xFF & messageDigest[i]); if (hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } return hexString.toString(); } /** * converts hex value string to normal string for use with RouterOS API * @param s - hex string to convert to * @return - converted string. */ static public String hexStrToStr(String s) { String ret = ""; for (int i = 0; i < s.length(); i += 2) { ret += (char) Integer.parseInt(s.substring(i, i + 2), 16); } return ret; } } public class ReadCommand implements Runnable { private DataInputStream in = null; private LinkedBlockingQueue queue = null; /** * Creates a new instance of CommandRead * @param in - Data input stream of socket * @param queue - data output inteface */ public ReadCommand(DataInputStream in, LinkedBlockingQueue queue) { this.in = in; this.queue = queue; } public void run() { byte b = 0; String s = ""; char ch; int sk, i, a = 0; while (true) { //int sk = 0; try { a = in.readByte(); } catch (IOException ex) { return; } if (a != 0 && a > 0) { if (a < 0x80) { sk = a; } else { if (a < 0xC0) { a = a << 8; try { a += in.readByte(); } catch (IOException ex) { return; } sk = a ^ 0x8000; } else { if (a < 0xE0) { try { for (i = 0; i < 2; i++) { a = a << 8; a += in.readByte(); } } catch (IOException ex) { Logger.getLogger(ReadCommand.class.getName()).log(Level.SEVERE, null, ex); return; } sk = a ^ 0xC00000; } else { if (a < 0xF0) { try { for (i = 0; i < 3; i++) { a = a << 8; a += in.readByte(); } } catch (IOException ex) { Logger.getLogger(ReadCommand.class.getName()).log(Level.SEVERE, null, ex); return; } sk = a ^ 3758096384L; } else { if (a < 0xF8) { try { a = 0; for (i = 0; i < 5; i++) { a = a << 8; a += in.readByte(); } } catch (IOException ex) { Logger.getLogger(ReadCommand.class.getName()).log(Level.SEVERE, null, ex); return; } } else { } } } } } s += "\n"; byte[] bb = new byte[sk]; try { a = in.read(bb, 0, sk); } catch (IOException ex) { a = 0; ex.printStackTrace(); return; } if (a > 0) { s += new String(bb); } } else if (b == -1) { System.out.println("Error, it should not happen ever, or connected to wrong port"); } else { try { queue.put(s); } catch (InterruptedException ex) { ex.printStackTrace(); System.out.println("exiting reader"); return; } s = ""; } } } } public class WriteCommand { private byte[] len = {0}; private DataOutputStream out = null; private String command = ""; WriteCommand(DataOutputStream out, String command) { this.out = out; this.command = command.replaceAll("\n", "").trim(); } WriteCommand(DataOutputStream out) { this.out = out; } public void setCommand(String command) { this.command = command.trim(); //return this; } String getCommand() { return command; } private byte[] writeLen(String command) { Integer i = null; String s = ""; String ret = ""; if (command.length() < 0x80) { i = command.length(); } else if (command.length() < 0x4000) { i = Integer.reverseBytes(command.length() | 0x8000); } else if (command.length() < 0x20000) { i = Integer.reverseBytes(command.length() | 0xC00000); } else if (command.length() < 10000000) { i = Integer.reverseBytes(command.length() | 3758096384L); } else { i = Integer.reverseBytes(command.length()); } s = Integer.toHexString(i); if (s.length() < 2) { return new byte[]{i.byteValue()}; } else { for (int j = 0; j < s.length(); j += 2) { ret += (char) Integer.parseInt(s.substring(j, j + 2), 16) != 0 ? (char) Integer.parseInt(s.substring(j, j + 2), 16) : ""; } } //char[] ch = ret.toCharArray(); return ret.getBytes(); } String runCommand() { int i, a, j; int counter; byte[] ret = new byte[0]; try { if (!command.contains("\n")) { byte[] b = writeLen(command); int retLen = b.length + command.length() + 1; ret = (byte[])Arrays.copyOf(ret, retLen); for (i = 0; i < b.length; i++) { ret[i] = b[i]; } //System.arraycopy(b, 0, ret, 0, b.length); //i = b.length; for (byte c : command.getBytes()) { //"US-ASCII" ret[i] = c; i = i + 1; } } else { String[] str = command.split("\n"); i = 1; int[] iTmp = new int[str.length]; for (a = 0; a < str.length; a++) { iTmp[a] = writeLen(str[a]).length + str[a].length(); } for (int b : iTmp) { i += b; } ret = (byte[])Arrays.copyOf(ret, i); counter = 0; for (a = 0; a < str.length; a++) { byte[] b = writeLen(str[a]); for (j = 0; j < b.length; j++) { ret[counter] = b[j]; counter = counter + 1; } for (byte c : str[a].getBytes()) { //"US-ASCII" ret[counter] = c; counter = counter + 1; } } } /*for(i = 0; i < ret.length; i++) { print(i.toString() + " : " + ret[i].toString()); }*/ out.write(ret, 0, ret.length); return "Sent successfully"; } catch (IOException ex) { Logger.getLogger(WriteCommand.class.getName()).log(Level.SEVERE, null, ex); return "failed"; } } } public class ApiConn /*extends Thread*/ { private Socket sock = null; private DataOutputStream out = null; private DataInputStream in = null; private String ipAddress; private int ipPort; private boolean connected = false; private String message = "Not connected"; private ReadCommand readCommand = null; private WriteCommand writeCommand = null; private Thread listener = null; private LinkedBlockingQueue queue = new LinkedBlockingQueue(40); /** * Constructor of the connection class * @param ipAddress - IP address of the router you want to conenct to * @param ipPort - port used for connection, ROS default is 8728 */ public ApiConn(String ipAddress, int ipPort) { this.ipAddress = ipAddress; this.ipPort = ipPort; //this.setName("settings"); } /** * State of connection * @return - if connection is established to router it returns true. */ public boolean isConnected() { return connected; } public void disconnect() throws IOException{ listener.interrupt(); sock.close(); } public void listen() { if (this.isConnected()) { if (readCommand == null) { readCommand = new ReadCommand(in, queue); } listener = new Thread(readCommand); listener.setDaemon(true); listener.setName("listener"); listener.start(); } } /** * to get IP address of the connection. Reads data from socket created. * @return InetAddress */ public InetAddress getIpAddress() { return sock == null ? null : sock.getInetAddress(); } /** * returns ip address that socket is asociated with. * @return InetAddress */ public InetAddress getLocalIpAddress() { return sock == null ? null : sock.getLocalAddress(); } /** * Socket remote port number * @return */ public int getPort() { return sock == null ? null : sock.getPort(); } /** * return local prot used by socket * @return */ public int getLocalPort() { return sock == null ? null : sock.getLocalPort(); } /** * Returns status message set up bu class. * @return */ public String getMessage() { return message; } /** * sets and exectues command (sends it to RouterOS host connected) * @param s - command will be sent to RouterOS for example "/ip/address/print\n=follow=" * @return */ public String sendCommand(String s) { writeCommand.setCommand(s); return writeCommand.runCommand(); } /** * exeecutes already set command. * @return returns status of the command sent */ public String runCommand() { return writeCommand.runCommand(); } /** * Tries to fech data that is repllied to commands sent. It will wait till it can return something. * @return returns data sent by RouterOS * @throws java.lang.InterruptedException */ public String getData() throws InterruptedException { String s = (String) queue.take(); return s; } /** * returns command that is set at this moment. And will be exectued if runCommand is exectued. * @return */ public String getCommand() { return writeCommand.getCommand(); } /** * set up method that will log you in * @param name - username of the user on the router * @param password - password for the user * @return */ public String login(String name, String password) { this.sendCommand("/login"); String s = "a"; String[] tmp; try { s = this.getData(); } catch (InterruptedException ex) { Logger.getLogger(ApiConn.class.getName()).log(Level.SEVERE, null, ex); return "failed read #1"; } if (!s.contains("!trap") && s.length() > 4) { tmp = s.trim().split("\n"); if (tmp.length > 1) { tmp = tmp[1].split("=ret="); s = ""; String transition = tmp[tmp.length - 1]; String chal = ""; chal = Hasher.hexStrToStr("00") + password + Hasher.hexStrToStr(transition); chal = Hasher.hashMD5(chal); String m = "/login\n=name=" + name + "\n=response=00" + chal; s = this.sendCommand(m); try { s = this.getData(); } catch (InterruptedException ex) { Logger.getLogger(ApiConn.class.getName()).log(Level.SEVERE, null, ex); return "failed read #2"; } if (s.contains("!done")) { if (!s.contains("!trap")) { return "Login successful"; } } } } return "Login failed"; } public void run() { try { InetAddress ia = InetAddress.getByName(ipAddress); if (ia.isReachable(1000)) { sock = new Socket(ipAddress, ipPort); in = new DataInputStream(sock.getInputStream()); out = new DataOutputStream(sock.getOutputStream()); connected = true; readCommand = new ReadCommand(in, queue); writeCommand = new WriteCommand(out); this.listen(); message = "Connected"; } else { message = "Not reachable"; } } catch (UnknownHostException ex) { connected = false; message = ex.getMessage(); ex.printStackTrace(); } catch (IOException ex) { connected = false; message = ex.getMessage(); ex.printStackTrace(); } } } public class ApiAnswer { private String[] Text; public ApiAnswer() {}; public ApiAnswer(String data) { Text = data.split("\n"); } public change(String data) { Text = data.split("\n"); } public String getParam(String param) { String[] tmp; String line; for(line: Text) { if (line.contains(param)) { tmp = line.split(param); if (tmp.length > 1) { return tmp[tmp.length - 1]; } else return ""; } } return ""; } public boolean isError() { String line; for (line: Text) { if (line.contains("!trap")) return true; } return false; } public boolean isDone() { String line; for (line: Text) { if (line.contains("!done")) return true; } return false; } public String[] getText() { return Text; } } public class ApiCommand { private String Text; public ApiCommand() { Text = ""; } public void clear() { Text = ""; } public void add(String line) { if(Text.length() == 0) { Text = line; } else { Text = Text + "\n" + line; } } public String getText() { return Text; } } И мой пример ее использования. Скрипт для шлюза Микротик с использованием выборки типа правил из вики. Код: 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.contract.bean.*; import bitel.billing.server.ipn.bean.*; import bitel.billing.server.ipn.*; import bitel.billing.server.util.*; //import bitel.billing.common.KernelConst; includeBGBS("bgbs://ru.bitel.bgbilling.kernel.script.common.bean.ScriptLibrary/mikrotik"); private getNewRule(status) { SERVICE_INTERNET = 27; SERVICE_INTRANET = 29; // 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", SERVICE_INTERNET); H.put("time", new GregorianCalendar()); ParseTarif(H); rule_id = H.get("rule_id"); //rule_id = 1; if (rule_id != null) { rule_type_manager = new RuleTypeManager(con,status.mid); status.ruleType = rule_type_manager.getType(Integer.parseInt(rule_id)); return status; } else return null; } private void 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 void 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 void 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); }; }; protected void doSync() { host = gate.getHost(); port = gate.getPort(); gateSetup = new DefaultServerSetup( gate.getConfig(), "\r\n" ); login = gateSetup.getStringValue( "login", "root" ); timeout = gateSetup.getIntValue( "timeout", 2000 ); pswd = gate.getKeyword(); ApiAnswer answer = new ApiAnswer(); ApiCommand command = new ApiCommand(); String str, lastRes, idList; boolean newIdList; String commandMark = "#"; ApiConn conn = new ApiConn(host, port); conn.run(); if (conn.isConnected()) { print(conn.login(login, pswd)); if ( log.isDebugEnabled() ) { log.info( " gate: " + host + ":" + port + " login: " + login + " pswd: " + pswd ); } session = null; try { command_list = null; for ( UserStatus status : statusList ) { cid = status.contractId; status = getNewRule(status); ruleType = status.ruleType; if (ruleType != null) { rule_id = ruleType.getId(); } else { rule_id = 0; }; rules = null; if ( status.status == IPNContractStatus.STATUS_OPEN ) { //открываем rules = getOpenRules( status ); log.info("OpenRules !!"+cid+"!!"); } else { if ( status.status == IPNContractStatus.STATUS_REMOVED ) { // удаляем rules = getDeleteRules( status ); log.info("DeleteRules !!"+cid+"!!"); } else { // закрываем rules = getCloseRules( status ); log.info("CloseRules !!"+cid+"!!"); }; }; if (rules != null) { lastRes = ""; idList = ""; for ( String rule : rules ) if (rule.length() > 0) { if((rule.indexOf(commandMark) == 0)&&(command.getText().length() > 0)) { print(command.getText()); print(conn.sendCommand(command.getText())); print("*****"); newIdList = true; do { str = conn.getData(); print(str); answer.change(str); command.clear(); if(answer.isError()) { print("error"); //str = conn.getData(); //print(str); } if(answer.getParam("=ret=").length() > 0) { lastRes = answer.getParam("=ret="); //print("result=" + lastRes); } if(answer.getParam("=.id=").length() > 0) { if (newIdList) { idList = answer.getParam("=.id="); newIdList = false; } else { idList = idList + "," + answer.getParam("=.id="); } } } while (!answer.isDone()); print("\n"); } else { str = rule; str = str.replaceAll("\\{RESULT\\}", lastRes); str = str.replaceAll("\\{LIST\\}", idList); command.add(str); }; } } else print("no rules"); } } catch( Exception e ) { throw new RuntimeException( e ); } finally { if ( conn.isConnected() ) { conn.disconnect(); } } } else throw new RuntimeException("Cannot connect to router"); } 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 ) { // пользовательское правило, без типа - то все оставляем как есть String ruleText = ManadUtils.getRule( status.gateType, status.ruleType ); //получаем списки адресов для данного клиента на текущий момент now = new java.util.GregorianCalendar(); ARM = new AddressRangeManager( con, status.mid); addressList = ARM.getContractAddressRange(status.contractId, now, 0); for (addressRange: addressList) { pool = addressRange.toShortString(); //приводим к нужному формату } pool = pool.replace(" ", ""); //получаем номер влана для клиента VLANID_PID = 9; CPM = new ContractParameterManager( con ); vlanid = CPM.getStringParam(status.contractId, VLANID_PID); // типизированное правило if ( status.ruleType != null ) { rule = generateRule( pool, status.gateType, status.ruleType, status.contractId, vlanid ); } else { rule = status.rule.getRuleText(); } 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; // return rule.split( "\n" ); } private generateRule( pool, gateType, ruleType, cid, vlanid ) { String rule; String ruleTypeData = ruleType.getData(); ruleTypeData.replaceAll("\r", ""); templates = ruleTypeData.split("\n"); ruleText = ManadUtils.getRule( gateType, ruleType ); replacements = new HashMap(); replacements.put( "\\{CID\\}", String.valueOf( cid ) ); replacements.put( "\\{VID\\}", String.valueOf( vlanid ) ); replacements.put( "\\{POOL\\}", pool ); //делаем подстановку макросов из текущего типа правила. for(String template : templates) { splitter = template.indexOf("="); key = template.substring(0, splitter - 1); //имя макроса value = template.substring(splitter + 1, template.length() - 1); //значение replacements.put("$\\{"+key+"\\}", value); }; addresses = ""; rule = ManadUtils.generateRule( ruleText, addresses, replacements, ruleType ); return rule; } Мне пришлось эмулировать работу команды find в виде отдельных макросов подстановки: {RESULT} - результат выполнения последней команды; {LIST} - список элементов, выданный последней командой. Другие макросы: {POOL} - выданный клиенту пул адресов, {VID} - введенный вручную номер влана, {CID} - номер договора. Команды для скриптового шлюза: Код: [DEFAULT] [OPEN] /ip/firewall/address-list/print ?=address={POOL} ?=list=closed_clients # /ip/firewall/address-list/remove =numbers={LIST} # /queue/simple/add =name=vlan{VID} =interface=vlan{VID} =limit-at=${upload}/${download} =max-limit=${upload}/${download} =disabled=no # [/OPEN] [CLOSE] /ip/firewall/address-list/add =address={POOL} =list=closed_clients =comment=!!{CID}!! # /queue/simple/remove =numbers=vlan{VID} # [/CLOSE] [DELETE] /ip/firewall/address-list/add =address={POOL} =list=closed_clients =comment=!!{CID}!! # /queue/simple/remove =numbers=vlan{VID} # [/DELETE] [/DEFAULT] Все команды отлично работают в версии биллинга 4.6 и должны работать в 5.0. |
Автор: | akubik [ 01 апр 2011, 18:17 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
Имеется ряд преимуществ по отношению к телнетовскому клиенту, такие как более высокая скорость работы, большая надежность. Самым же главным отличием является положительная обратная связь - можно отслеживать реакцию на свои команды. И сам ответ микротика более машинно-ориентирован, в нем нет никаких лишних символов форматирования и нет такой несуразицы как три приглашения к вводу от одной команды и ни одного - от другой. |
Автор: | snark [ 03 апр 2011, 16:13 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
перенесите все в вики и напишите там "тема для обсуждения" (ссылка на эту тему) - так код будет в одном месте (более подходящем для этого, IMHO), а обсуждение в другом |
Автор: | stark [ 05 апр 2011, 16:50 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
сделал ссылку сюда: http://wiki.bgbilling.ru/index.php/%D0% ... API_Client |
Автор: | snark [ 05 апр 2011, 16:59 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
"работающий по Mikrotik API"? может все же лучше "работающий через Mikrotik API" или "работающий с помощью Mikrotik API"? |
Автор: | stark [ 05 апр 2011, 17:11 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
snark писал(а): "работающий по Mikrotik API"? может все же лучше "работающий через Mikrotik API" или "работающий с помощью Mikrotik API"? fixed |
Автор: | stark [ 05 апр 2011, 17:12 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
а вот это похоже первоисточник : http://wiki.mikrotik.com/wiki/API_in_Java |
Автор: | akubik [ 08 апр 2011, 13:41 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
stark писал(а): Так и есть. |
Автор: | Sirrin [ 11 апр 2011, 15:21 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
Уважаемый akubik! Не могли бы Вы описать детальнее процедуру создания рабочего шлюза? По какому сетевому протоколу (если он есть) общается биллинг с микротиком посредством скрипта и т.д. |
Автор: | akubik [ 14 апр 2011, 11:19 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
Итак данный скрипт соединяется с оборудованием на RouterOS по сетевому протоколу TCP к порту 8728. Далее через это соединение он отправляет запросы и получает ответы. Для того чтобы это заработало в самом маршрутизаторе нужно открыть службу API. Код: [sysadmin@CORE] > ip service enable api Ну и разумеется предусмотреть свободный проход пакетов через фаерволы, если такие имеются. Команды отправляются по одной в виде набора строк, заканчивающейся нулевым символом. Сам протокол связи достаточно сложен, однако используя данную библиотеку все упрощается, и команды представляются в виде простого набора строк. В частности: Код: /ip/address/add =interface=ether1 =address=10.0.0.1/24 Команды для работы с микротиком частично дублируют свои аналоги из коммандной оболочки, частично являются оригинальными. Подробней об этом можно почитать по ссылке: http://wiki.mikrotik.com/wiki/Manual:API |
Автор: | akubik [ 14 апр 2011, 11:34 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
Если убрать лишнюю шелуху то алгоритм работы с библиотекой будет выглядеть так: Код: ApiAnswer answer = new ApiAnswer(); ApiCommand command = new ApiCommand(); ApiConn conn = new ApiConn(host, port); String str; conn.run(); //Подключаемся к микротику if (!conn.isConnected()) { print("Cannot connect!"); exit; } command.add("/ip/address/add"); //Задаем какую-нибудь команду command.add("=interface=ether1"); command.add("=address=10.0.0.1/24"); conn.sendCommand(command.getText());//Отправляем ее микротику str = conn.getData(); answer.change(str); if (answer.isError()) print("Error " + str); else print("OK"); command.clear(); //готовимся к отправке слудующей команды. В случае если команда выводит список, то принимать данные придется в цикле до тех пор пока в строках, выдаваемых conn.getData() не встретится "done!". |
Автор: | stark [ 21 июн 2012, 15:21 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
Добавил в 5.2 обертку для Mikrotik Api. MikrotikApiSession. |
Автор: | stark [ 21 июн 2012, 15:45 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
А команды в шлюзе можно писать по старому , а в скрипте шлюза сделать преобразование (разбить на строки, начинающиеся с "=", заменить пробелы на "/" ). |
Автор: | mikos [ 25 янв 2013, 18:12 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
Всем доброго дня. Может кто подсобит добавить сюда таймаут? Через какое-то время подозреваю подвисание задачи открытия шлюза и начинают копиться задачи, из-за чего вскоре перестает работать шедалер. Хотелось бы, чтобы в случае проблем с коннектом или получением ответов от шлюза, скрипт не подвисал, а завершался по таймауту. Таймаут на коннект вроде есть: Код: public void run() { try { InetAddress ia = InetAddress.getByName(ipAddress); if (ia.isReachable(1000)) { sock = new Socket(ipAddress, ipPort); in = new DataInputStream(sock.getInputStream()); out = new DataOutputStream(sock.getOutputStream()); connected = true; readCommand = new ReadCommand(in, queue); writeCommand = new WriteCommand(out); this.listen(); message = "Connected"; Но я подозреваю, что коннект проходит, а вот ответов от нее не доходит... (( Буду очень благодарен за помощь! PS: Версия биллинга 5.1 |
Автор: | mikos [ 25 янв 2013, 21:33 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
Висит уже десяток минут. В логах шедалера движение прекратилось, но в планировщике вижу одну запущенную задачу... Вывод статуса шедалера Код: #./scheduler_status.sh Sending 'status' on 127.0.0.1:9066 Result: TaskExecuter working Started: 25.01.2013 18:29:38 Uptime: 0 d 01:00:52 Memory total: 411 041 792; max: 1 035 993 088; free: 273 795 200 Memory pools: Non-heap memory[Code Cache]: max: 50 331 648; used: 6 376 256; peek: 6 509 504 Heap memory[PS Eden Space]: max: 39 845 888; used: 27 216 856; peek: 119 275 520 Heap memory[PS Survivor Space]: max: 39 845 888; used: 544 168; peek: 39 845 888 Heap memory[PS Old Gen]: max: 956 301 312; used: 109 485 568; peek: 363 924 472 Non-heap memory[PS Perm Gen]: max: 67 108 864; used: 17 976 048; peek: 17 976 048 Thread count: 128 Trees in cache: 92 Periodic tasks executed: 64; active: 1 Urgent tasks executed: 1; active: 0 Connections pool to Master status Idle: 20; Active: 3; maxActive: 300; maxIdle: 20 Не пойму что происходит и как отловить проблему, суть которой - накопление запущенных периодических задачь... |
Автор: | stark [ 28 янв 2013, 17:03 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
mikos писал(а): Всем доброго дня. Может кто подсобит добавить сюда таймаут? Через какое-то время подозреваю подвисание задачи открытия шлюза и начинают копиться задачи, из-за чего вскоре перестает работать шедалер. Хотелось бы, чтобы в случае проблем с коннектом или получением ответов от шлюза, скрипт не подвисал, а завершался по таймауту. Таймаут на коннект вроде есть: Код: public void run() { try { InetAddress ia = InetAddress.getByName(ipAddress); if (ia.isReachable(1000)) { sock = new Socket(ipAddress, ipPort); in = new DataInputStream(sock.getInputStream()); out = new DataOutputStream(sock.getOutputStream()); connected = true; readCommand = new ReadCommand(in, queue); writeCommand = new WriteCommand(out); this.listen(); message = "Connected"; Но я подозреваю, что коннект проходит, а вот ответов от нее не доходит... (( Буду очень благодарен за помощь! PS: Версия биллинга 5.1 Код: sock.setSoTimeout( xxxx);
|
Автор: | skyb [ 22 авг 2013, 15:52 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
stark писал(а): Добавил в 5.2 обертку для Mikrotik Api. MikrotikApiSession. ненашел как в доке пользоваться, можно поподробней |
Автор: | stark [ 22 авг 2013, 16:59 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
skyb писал(а): stark писал(а): Добавил в 5.2 обертку для Mikrotik Api. MikrotikApiSession. ненашел как в доке пользоваться, можно поподробней Для inet есть такой пример . http://wiki.bgbilling.ru/index.php/%D0% ... krotik_api) И класс MikrotikServiceActivator в диначическом коде. В нем Код: @Override protected void executeCommand( String command ) throws Exception { logger.info( "execute: " + command ); command = command.replace( "\\n", "\n" ); String result = session.doCommand( command ); logger.info( "result=" + result ); } По аналогии можно и для IPN сделать. |
Автор: | skyb [ 22 авг 2013, 17:59 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
я так понял для ipn уже сделано, интересует ipn |
Автор: | stark [ 22 авг 2013, 18:23 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
skyb писал(а): я так понял для ipn уже сделано, интересует ipn цикл однако бесконечный |
Автор: | skyb [ 22 авг 2013, 19:08 ] |
Заголовок сообщения: | Re: Mikrotik API Client |
stark писал(а): skyb писал(а): я так понял для ipn уже сделано, интересует ipn цикл однако бесконечный да не, мне интересно как использовать в ipn этот api если он реализован_) |
Страница 1 из 1 | Часовой пояс: UTC + 5 часов [ Летнее время ] |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |