Module netmiko.fortinet
Sub-modules
netmiko.fortinet.fortinet_ssh
Classes
class FortinetSSH (*args: Any, **kwargs: Any)
-
Class for platforms that have no config mode.
check_config_mode returns True as the expectation is that configuration commands can be executed directly. So in your current state, you are in "config mode" i.e. you can make configuration changes.
If you truly cannot make any configuration changes to device then you should probably overwrite check_config_mode in the platform specific driver and return False.
Expand source code
class FortinetSSH(NoConfig, NoEnable, CiscoSSHConnection): prompt_pattern = r"[#$]" preferred_kex = { "diffie-hellman-group14-sha1", "diffie-hellman-group-exchange-sha1", "diffie-hellman-group-exchange-sha256", "diffie-hellman-group1-sha1", } def __init__(self, *args: Any, **kwargs: Any) -> None: disabled_algorithms = kwargs.get("disabled_algorithms") # Set this as long as no "kex" settings being passed via disabled_algorithms if disabled_algorithms is None or not disabled_algorithms.get("kex"): paramiko_transport = getattr(paramiko, "Transport") paramiko_cur_kex = set(paramiko_transport._preferred_kex) # Disable any kex not in allowed fortinet set disabled_kex = list(paramiko_cur_kex - self.preferred_kex) kwargs["disabled_algorithms"] = {"kex": disabled_kex} super().__init__(*args, **kwargs) def _try_session_preparation(self, force_data: bool = False) -> None: super()._try_session_preparation(force_data=force_data) def session_preparation(self) -> None: """Prepare the session after the connection has been established.""" data = self._test_channel_read(pattern=f"to accept|{self.prompt_pattern}") # If "set post-login-banner enable" is set it will require you to press 'a' # to accept the banner before you login. This will accept if it occurs if "to accept" in data: self.write_channel("a\r") self._test_channel_read(pattern=self.prompt_pattern) self.set_base_prompt() self._vdoms = self._vdoms_enabled() self._os_version = self._determine_os_version() # Retain how the 'output mode' was original configured. self._original_output_mode = self._get_output_mode() self._output_mode = self._original_output_mode self.disable_paging() def set_base_prompt( self, pri_prompt_terminator: str = r"#", alt_prompt_terminator: str = r"$", delay_factor: float = 1.0, pattern: Optional[str] = None, ) -> str: if not pattern: pattern = self.prompt_pattern return super().set_base_prompt( pri_prompt_terminator=pri_prompt_terminator, alt_prompt_terminator=alt_prompt_terminator, delay_factor=delay_factor, pattern=pattern, ) def find_prompt( self, delay_factor: float = 1.0, pattern: Optional[str] = None ) -> str: if not pattern: pattern = self.prompt_pattern return super().find_prompt( delay_factor=delay_factor, pattern=pattern, ) def _vdoms_enabled(self) -> bool: """Determine whether virtual domains are enabled or not.""" check_command = "get system status | grep Virtual" output = self._send_command_str( check_command, expect_string=self.prompt_pattern ) return bool( re.search( r"Virtual domain configuration: (multiple|enable|split-task)", output ) ) def _config_global(self) -> str: """Enter 'config global' mode, raise a ValueError exception on failure.""" try: return self._send_command_str( "config global", expect_string=self.prompt_pattern ) except Exception: msg = """ Netmiko may require 'config global' access to properly disable output paging. Alternatively you can try configuring 'configure system console -> set output standard'. """ raise ValueError(msg) def _exit_config_global(self) -> str: """Exit 'config global' mode.""" try: return self._send_command_str("end", expect_string=self.prompt_pattern) except Exception: msg = "Unable to properly exit 'config global' mode." raise ValueError(msg) def disable_paging( self, command: str = "terminal length 0", delay_factor: Optional[float] = None, cmd_verify: bool = True, pattern: Optional[str] = None, ) -> str: """Disable paging is only available with specific roles so it may fail.""" output = "" if self._output_mode == "standard": # Do nothing - already correct. return "" if self._vdoms: output += self._config_global() disable_paging_commands = [ "config system console", "set output standard", "end", ] output += self.send_multiline( disable_paging_commands, expect_string=self.prompt_pattern ) self._output_mode = "standard" if self._vdoms: output += self._exit_config_global() return output def _determine_os_version(self) -> str: check_command = "get system status | grep Version" output = self._send_command_str( check_command, expect_string=self.prompt_pattern ) if re.search(r"^Version: .* (v[78]\.).*$", output, flags=re.M): return "v7_or_later" elif re.search(r"^Version: .* (v[654]\.).*$", output, flags=re.M): return "v6_or_earlier" else: raise ValueError("Unexpected FortiOS Version encountered.") def _get_output_mode_v6(self) -> str: """ FortiOS V6 and earlier. Retrieve the current output mode. """ if self._vdoms: self._config_global() output = self._send_command_str("show full-configuration system console") if self._vdoms: self._exit_config_global() pattern = r"^\s+set output (?P<mode>\S+)\s*$" result_mode_re = re.search(pattern, output, flags=re.M) if result_mode_re: result_mode = result_mode_re.group("mode").strip() if result_mode in ["more", "standard"]: return result_mode raise ValueError("Unable to determine the output mode on the Fortinet device.") def _get_output_mode_v7(self) -> str: """ FortiOS V7 and later. Retrieve the current output mode. """ if self._vdoms: self._config_global() output = self._send_command_str( "get system console", expect_string=self.prompt_pattern ) if self._vdoms: self._exit_config_global() pattern = r"output\s+:\s+(?P<mode>\S+)\s*$" result_mode_re = re.search(pattern, output, flags=re.M) if result_mode_re: result_mode = result_mode_re.group("mode").strip() if result_mode in ["more", "standard"]: return result_mode raise ValueError("Unable to determine the output mode on the Fortinet device.") def _get_output_mode(self) -> str: """Save the state of the output mode so it can be reset at the end of the session.""" # Fortios Version6 does not support 'get system console' if "v6" in self._os_version: return self._get_output_mode_v6() elif "v7" in self._os_version: return self._get_output_mode_v7() else: raise ValueError("Unexpected FortiOS Version encountered.") def cleanup(self, command: str = "exit") -> None: """Re-enable paging globally.""" output = "" if self._original_output_mode == "more": if self._vdoms: output += self._config_global() commands = [ "config system console", "set output more", "end", ] output += self.send_multiline(commands, expect_string=self.prompt_pattern) if self._vdoms: self._exit_config_global() return super().cleanup(command=command) def save_config( self, cmd: str = "", confirm: bool = False, confirm_response: str = "" ) -> str: """Not Implemented""" raise NotImplementedError
Ancestors
Class variables
var preferred_kex
var prompt_pattern
Methods
def cleanup(self, command: str = 'exit') ‑> None
-
Re-enable paging globally.
def disable_paging(self, command: str = 'terminal length 0', delay_factor: Optional[float] = None, cmd_verify: bool = True, pattern: Optional[str] = None) ‑> str
-
Disable paging is only available with specific roles so it may fail.
def save_config(self, cmd: str = '', confirm: bool = False, confirm_response: str = '') ‑> str
-
Not Implemented
def session_preparation(self) ‑> None
-
Prepare the session after the connection has been established.
Inherited members
CiscoSSHConnection
:check_config_mode
check_enable_mode
clear_buffer
commit
config_mode
disconnect
enable
establish_connection
exit_config_mode
exit_enable_mode
find_prompt
is_alive
normalize_cmd
normalize_linefeeds
paramiko_cleanup
read_channel
read_channel_timing
read_until_pattern
read_until_prompt
read_until_prompt_or_pattern
run_ttp
select_delay_factor
send_command
send_command_expect
send_command_timing
send_config_from_file
send_config_set
send_multiline
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
strip_backspaces
strip_command
strip_prompt
telnet_login
write_channel