tomaae.homeassistant-mikrot.../custom_components/mikrotik_router/mikrotikapi.py

166 lines
5 KiB
Python
Raw Normal View History

2019-12-02 01:13:28 +01:00
"""Mikrotik API for Mikrotik Router."""
import ssl
import logging
import librouteros
2019-12-02 01:13:28 +01:00
_LOGGER = logging.getLogger(__name__)
2019-12-02 03:19:07 +01:00
2019-12-02 17:59:49 +01:00
# ---------------------------
2019-12-02 01:13:28 +01:00
# MikrotikAPI
2019-12-02 17:59:49 +01:00
# ---------------------------
2019-12-02 01:13:28 +01:00
class MikrotikAPI:
2019-12-02 18:13:55 +01:00
"""Handle all communication with the Mikrotik API."""
2019-12-02 18:13:55 +01:00
def __init__(self, host, username, password, port=0, use_ssl=True, login_method="plain", encoding="utf-8"):
"""Initialize the Mikrotik Client."""
self._host = host
self._use_ssl = use_ssl
self._port = port
self._username = username
self._password = password
self._login_method = login_method
self._encoding = encoding
self._ssl_wrapper = None
2019-12-02 18:13:55 +01:00
self._connection = None
self._connected = False
self.error = ""
2019-12-02 18:13:55 +01:00
# Default ports
if not self._port:
self._port = 8729 if self._use_ssl else 8728
2019-12-02 18:13:55 +01:00
# ---------------------------
# connect
# ---------------------------
def connect(self):
"""Connect to Mikrotik device."""
self.error = ""
2019-12-05 22:10:42 +01:00
self._connected = None
2019-12-02 18:13:55 +01:00
kwargs = {
"encoding": self._encoding,
"login_methods": self._login_method,
"port": self._port,
}
2019-12-02 18:13:55 +01:00
if self._use_ssl:
if self._ssl_wrapper is None:
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
self._ssl_wrapper = ssl_context.wrap_socket
kwargs["ssl_wrapper"] = self._ssl_wrapper
2019-12-02 18:13:55 +01:00
try:
self._connection = librouteros.connect(self._host, self._username, self._password, **kwargs)
except (
2019-12-02 19:22:34 +01:00
librouteros.exceptions.TrapError,
librouteros.exceptions.MultiTrapError,
librouteros.exceptions.ConnectionClosed,
librouteros.exceptions.ProtocolError,
librouteros.exceptions.FatalError
2019-12-02 18:13:55 +01:00
) as api_error:
_LOGGER.error("Mikrotik %s: %s", self._host, api_error)
self.error_to_strings("%s" % api_error)
self._connection = None
return False
else:
_LOGGER.info("Mikrotik Connected to %s", self._host)
self._connected = True
2019-12-02 18:13:55 +01:00
return self._connected
2019-12-02 18:13:55 +01:00
# ---------------------------
# error_to_strings
# ---------------------------
def error_to_strings(self, error):
"""Translate error output to error string."""
2019-12-02 18:13:55 +01:00
self.error = "cannot_connect"
if error == "invalid user name or password (6)":
self.error = "wrong_login"
2019-12-02 18:13:55 +01:00
return
2019-12-02 18:13:55 +01:00
# ---------------------------
# connected
# ---------------------------
def connected(self):
"""Return connected boolean."""
return self._connected
2019-12-02 18:13:55 +01:00
# ---------------------------
# path
# ---------------------------
def path(self, path):
"""Retrieve data from Mikrotik API."""
if not self._connected or not self._connection:
if not self.connect():
return None
2019-12-02 18:13:55 +01:00
try:
response = self._connection.path(path)
tuple(response)
except librouteros.exceptions.ConnectionClosed:
_LOGGER.error("Mikrotik %s connection closed", self._host)
self._connected = False
self._connection = None
return None
except (
2019-12-02 19:22:34 +01:00
librouteros.exceptions.TrapError,
librouteros.exceptions.MultiTrapError,
librouteros.exceptions.ProtocolError,
librouteros.exceptions.FatalError
2019-12-02 18:13:55 +01:00
) as api_error:
_LOGGER.error("Mikrotik %s connection error %s", self._host, api_error)
return None
2019-12-02 18:13:55 +01:00
return response if response else None
2019-12-03 01:47:38 +01:00
# ---------------------------
# update
# ---------------------------
def update(self, path, param, value, mod_param, mod_value):
"""Modify a parameter"""
2019-12-03 01:47:38 +01:00
response = self.path(path)
if response is None:
return False
2019-12-03 01:47:38 +01:00
for tmp in response:
if param not in tmp:
continue
2019-12-03 01:47:38 +01:00
if tmp[param] != value:
continue
2019-12-03 01:47:38 +01:00
params = {
'.id': tmp['.id'],
mod_param: mod_value
}
2019-12-04 20:13:11 +01:00
response.update(**params)
2019-12-04 20:13:11 +01:00
return True
2019-12-04 20:13:11 +01:00
# ---------------------------
# run_script
# ---------------------------
def run_script(self, name):
"""Run script"""
2019-12-04 20:13:11 +01:00
response = self.path('/system/script')
if response is None:
return False
2019-12-04 20:13:11 +01:00
for tmp in response:
if 'name' not in tmp:
continue
2019-12-04 20:13:11 +01:00
if tmp['name'] != name:
continue
2019-12-04 20:13:11 +01:00
run = response('run', **{'.id': tmp['.id']})
tuple(run)
2019-12-04 20:13:11 +01:00
return True