Module netmiko.mikrotik
Sub-modules
netmiko.mikrotik.mikrotik_ssh
Classes
class MikrotikRouterOsFileTransfer (ssh_conn: BaseConnection,
source_file: str,
dest_file: str,
file_system: str | None = 'flash',
direction: str = 'put',
socket_timeout: float = 10.0,
progress: Callable[..., Any] | None = None,
progress4: Callable[..., Any] | None = None,
hash_supported: bool = False)-
Expand source code
class MikrotikRouterOsFileTransfer(BaseFileTransfer): """Mikrotik Router Os File Transfer driver.""" def __init__( self, ssh_conn: BaseConnection, source_file: str, dest_file: str, file_system: Optional[str] = "flash", direction: str = "put", socket_timeout: float = 10.0, progress: Optional[Callable[..., Any]] = None, progress4: Optional[Callable[..., Any]] = None, hash_supported: bool = False, ) -> None: super().__init__( ssh_conn=ssh_conn, source_file=source_file, dest_file=dest_file, file_system=file_system, direction=direction, socket_timeout=socket_timeout, progress=progress, progress4=progress4, hash_supported=hash_supported, ) def check_file_exists(self, remote_cmd: str = "") -> bool: """Check if the dest_file already exists on the file system.""" if self.direction == "put": if not remote_cmd: remote_cmd = f'/file print detail where name="{self.file_system}/{self.dest_file}"' remote_out = self.ssh_ctl_chan._send_command_timing_str(remote_cmd) # Possible outputs: # - Normal entry containing 'size' and the filename # 0 name="flash/test9.txt" type=".txt file" size=19 creation-time=... # - Some firmware versions print flags then the entry # Flags: S - shared # 0 name="flash/test9.txt" type=".txt file" size=19 creation-time=... # - Or only the flags (no matching file), or entirely blank on failure # Flags: S - shared # <no matching file line> if "size" in remote_out and f"{self.file_system}/{self.dest_file}" in remote_out: return True elif not remote_out.strip() or ("Flags:" in remote_out and "size" not in remote_out): return False raise ValueError("Unexpected output from check_file_exists") elif self.direction == "get": return os.path.exists(self.dest_file) else: raise ValueError("Unexpected value for self.direction") def remote_space_available(self, search_pattern: str = "") -> int: """Return space available on remote device.""" remote_cmd = "system resource print without-paging" sys_res = self.ssh_ctl_chan._send_command_timing_str(remote_cmd).splitlines() for res in sys_res: if "free-memory" in res: space_str = res.strip().replace("free-memory: ", "") return self._format_to_bytes(space_str) raise ValueError("Unexpected output from remote_space_available") def remote_file_size(self, remote_cmd: str = "", remote_file: Optional[str] = None) -> int: """Get the file size of the remote file.""" if remote_file is None: if self.direction == "put": remote_file = self.dest_file elif self.direction == "get": remote_file = self.source_file else: raise ValueError("Invalid value for file transfer direction.") if not remote_cmd: remote_cmd = f'/file print detail where name="{self.file_system}/{remote_file}"' remote_out = self.ssh_ctl_chan._send_command_timing_str(remote_cmd) try: size = remote_out.split("size=")[1].split(" ")[0] return self._format_to_bytes(size) except (KeyError, IndexError): raise ValueError("Unable to find file on remote system") def file_md5(self, file_name: str, add_newline: bool = False) -> str: raise AttributeError("RouterOS does not natively support an MD5-hash operation.") @staticmethod def process_md5(md5_output: str, pattern: str = "") -> str: raise AttributeError("RouterOS does not natively support an MD5-hash operation.") def compare_md5(self) -> bool: raise AttributeError("RouterOS does not natively support an MD5-hash operation.") def remote_md5(self, base_cmd: str = "", remote_file: Optional[str] = None) -> str: raise AttributeError("RouterOS does not natively support an MD5-hash operation.") def verify_file(self) -> bool: """ Verify the file has been transferred correctly based on filesize. This method is very approximate as Mikrotik rounds file sizes to KiB, MiB, GiB... Therefore multiple conversions from/to bytes are needed """ if self.direction == "put": local_size = self._format_bytes(os.stat(self.source_file).st_size) remote_size = self._format_bytes(self.remote_file_size(remote_file=self.dest_file)) return local_size == remote_size elif self.direction == "get": local_size = self._format_bytes(os.stat(self.dest_file).st_size) remote_size = self._format_bytes(self.remote_file_size(remote_file=self.source_file)) return local_size == remote_size else: raise ValueError("Unexpected value of self.direction") @staticmethod def _format_to_bytes(size: str) -> int: """ Internal function to convert Mikrotik size to bytes """ if size.endswith("KiB"): return round(int(float(size.replace("KiB", "")) * 1024)) if size.endswith("MiB"): return round(int(float(size.replace("MiB", "")) * 1048576)) if size.endswith("GiB"): return round(int(float(size.replace("GiB", "")) * 1073741824)) return round(int(size)) @staticmethod def _format_bytes(size: int) -> str: """ Internal function to convert bytes to KiB, MiB or GiB Extremely approximate """ n = 0 levels = {0: "", 1: "Ki", 2: "Mi", 3: "Gi"} while size > 4096 and n < 3: size = round(size / 1024) n += 1 return f"{size}{levels[n]}B"Mikrotik Router Os File Transfer driver.
Ancestors
Methods
def check_file_exists(self, remote_cmd: str = '') ‑> bool-
Expand source code
def check_file_exists(self, remote_cmd: str = "") -> bool: """Check if the dest_file already exists on the file system.""" if self.direction == "put": if not remote_cmd: remote_cmd = f'/file print detail where name="{self.file_system}/{self.dest_file}"' remote_out = self.ssh_ctl_chan._send_command_timing_str(remote_cmd) # Possible outputs: # - Normal entry containing 'size' and the filename # 0 name="flash/test9.txt" type=".txt file" size=19 creation-time=... # - Some firmware versions print flags then the entry # Flags: S - shared # 0 name="flash/test9.txt" type=".txt file" size=19 creation-time=... # - Or only the flags (no matching file), or entirely blank on failure # Flags: S - shared # <no matching file line> if "size" in remote_out and f"{self.file_system}/{self.dest_file}" in remote_out: return True elif not remote_out.strip() or ("Flags:" in remote_out and "size" not in remote_out): return False raise ValueError("Unexpected output from check_file_exists") elif self.direction == "get": return os.path.exists(self.dest_file) else: raise ValueError("Unexpected value for self.direction")Check if the dest_file already exists on the file system.
def verify_file(self) ‑> bool-
Expand source code
def verify_file(self) -> bool: """ Verify the file has been transferred correctly based on filesize. This method is very approximate as Mikrotik rounds file sizes to KiB, MiB, GiB... Therefore multiple conversions from/to bytes are needed """ if self.direction == "put": local_size = self._format_bytes(os.stat(self.source_file).st_size) remote_size = self._format_bytes(self.remote_file_size(remote_file=self.dest_file)) return local_size == remote_size elif self.direction == "get": local_size = self._format_bytes(os.stat(self.dest_file).st_size) remote_size = self._format_bytes(self.remote_file_size(remote_file=self.source_file)) return local_size == remote_size else: raise ValueError("Unexpected value of self.direction")Verify the file has been transferred correctly based on filesize. This method is very approximate as Mikrotik rounds file sizes to KiB, MiB, GiB… Therefore multiple conversions from/to bytes are needed
Inherited members
class MikrotikRouterOsSSH (**kwargs: Any)-
Expand source code
class MikrotikRouterOsSSH(MikrotikBase): """Mikrotik RouterOS SSH driver.""" passMikrotik RouterOS SSH driver.
Ancestors
Inherited members
MikrotikBase:check_config_modecheck_enable_modecleanupclear_buffercommitconfig_modedisable_pagingdisconnectenableenable_secret_handlerestablish_connectionexit_config_modeexit_enable_modefind_promptis_alivenormalize_cmdnormalize_linefeedsparamiko_cleanupread_channelread_channel_timingread_until_patternread_until_promptread_until_prompt_or_patternrun_ttpsave_configselect_delay_factorsend_commandsend_command_expectsend_command_timingsend_config_from_filesend_config_setsend_multilinesession_preparationset_base_promptset_terminal_widthspecial_login_handlerstrip_ansi_escape_codesstrip_backspacesstrip_commandstrip_prompttelnet_loginwrite_channel
class MikrotikSwitchOsSSH (**kwargs: Any)-
Expand source code
class MikrotikSwitchOsSSH(MikrotikBase): """Mikrotik SwitchOS SSH driver.""" passMikrotik SwitchOS SSH driver.
Ancestors
Inherited members
MikrotikBase:check_config_modecheck_enable_modecleanupclear_buffercommitconfig_modedisable_pagingdisconnectenableenable_secret_handlerestablish_connectionexit_config_modeexit_enable_modefind_promptis_alivenormalize_cmdnormalize_linefeedsparamiko_cleanupread_channelread_channel_timingread_until_patternread_until_promptread_until_prompt_or_patternrun_ttpsave_configselect_delay_factorsend_commandsend_command_expectsend_command_timingsend_config_from_filesend_config_setsend_multilinesession_preparationset_base_promptset_terminal_widthspecial_login_handlerstrip_ansi_escape_codesstrip_backspacesstrip_commandstrip_prompttelnet_loginwrite_channel