diff --git a/.github/workflows/commit.yaml b/.github/workflows/commit.yaml index df351a5b8..3ec16bfbd 100644 --- a/.github/workflows/commit.yaml +++ b/.github/workflows/commit.yaml @@ -1,13 +1,15 @@ --- name: build on: [push, pull_request] +env: + environment: gh_actions jobs: std_tests: runs-on: ubuntu-latest strategy: max-parallel: 4 matrix: - python-version: [3.6, 3.7, 3.8, 3.9, 3.10.0] + python-version: [3.7, 3.8, 3.9, 3.10.0] steps: - name: Checkout repository diff --git a/docs/netmiko/aruba/aruba_ssh.html b/docs/netmiko/aruba/aruba_ssh.html index 68912a967..f6d8f5dd9 100644 --- a/docs/netmiko/aruba/aruba_ssh.html +++ b/docs/netmiko/aruba/aruba_ssh.html @@ -52,7 +52,7 @@
netmiko.aruba.aruba_ssh
netmiko.base_connection
netmiko.base_connection
netmiko.base_connection
-def enable(self, cmd='', pattern='ssword', enable_pattern=None, re_flags=)
+def enable(self, cmd='', pattern='ssword', enable_pattern=None, re_flags=re.IGNORECASE)
Enter enable mode.
@@ -5711,7 +5711,7 @@netmiko.cisco.cisco_ios
+def set_base_prompt(self, pri_prompt_terminator='#', alt_prompt_terminator='>', delay_factor=1.0, pattern=None)
+
Cisco IOS/IOS-XE abbreviates the prompt at 20-chars in config mode.
+Consequently, abbreviate the base_prompt
def set_base_prompt(
+ self,
+ pri_prompt_terminator: str = "#",
+ alt_prompt_terminator: str = ">",
+ delay_factor: float = 1.0,
+ pattern: Optional[str] = None,
+) -> str:
+ """
+ Cisco IOS/IOS-XE abbreviates the prompt at 20-chars in config mode.
+
+ Consequently, abbreviate the base_prompt
+ """
+ base_prompt = super().set_base_prompt(
+ pri_prompt_terminator=pri_prompt_terminator,
+ alt_prompt_terminator=alt_prompt_terminator,
+ delay_factor=delay_factor,
+ pattern=pattern,
+ )
+ self.base_prompt = base_prompt[:16]
+ return self.base_prompt
+send_config_from_file
send_config_set
send_multiline
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
send_config_set
send_multiline
session_preparation
set_base_prompt
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
send_config_set
send_multiline
session_preparation
set_base_prompt
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
send_config_set
send_multiline
session_preparation
set_base_prompt
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
save_config
session_preparation
+set_base_prompt
netmiko.cisco.cisco_nxos_ssh
-def check_config_mode(self, check_string=')#', pattern='#')
+def check_config_mode(self, check_string=')#', pattern='[>#]')
Checks if the device is in configuration mode or not.
def check_config_mode(self, check_string: str = ")#", pattern: str = "#") -> bool:
+def check_config_mode(
+ self, check_string: str = ")#", pattern: str = r"[>#]"
+) -> bool:
"""Checks if the device is in configuration mode or not."""
return super().check_config_mode(check_string=check_string, pattern=pattern)
netmiko.cisco.cisco_wlc_ssh
netmiko.cisco.cisco_wlc_ssh
netmiko.cisco.cisco_wlc_ssh
For 'show run-config' Cisco WLC adds a 'Press Enter to continue…' message -Even though pagination is disabled -show run-config also has excessive delays in the output which requires special -handling. -Arguments are the same as send_command_timing() method
show run-config also has excessive delays in the output which requires special +handling.
+Arguments are the same as send_command_timing() method.
def send_command_w_enter(self, *args: Any, **kwargs: Any) -> str:
"""
For 'show run-config' Cisco WLC adds a 'Press Enter to continue...' message
- Even though pagination is disabled
+ Even though pagination is disabled.
+
show run-config also has excessive delays in the output which requires special
handling.
- Arguments are the same as send_command_timing() method
+
+ Arguments are the same as send_command_timing() method.
"""
if len(args) > 1:
raise ValueError("Must pass in delay_factor as keyword argument")
@@ -733,17 +791,18 @@ Methods
kwargs["delay_factor"] = self.select_delay_factor(delay_factor)
output = self._send_command_timing_str(*args, **kwargs)
+ second_args = list(args)
+ if len(args) == 1:
+ second_args[0] = self.RETURN
+ else:
+ kwargs["command_string"] = self.RETURN
+ if not kwargs.get("max_loops"):
+ kwargs["max_loops"] = 150
+
if "Press any key" in output or "Press Enter to" in output:
- new_args = list(args)
- if len(args) == 1:
- new_args[0] = self.RETURN
- else:
- kwargs["command_string"] = self.RETURN
- if not kwargs.get("max_loops"):
- kwargs["max_loops"] = 150
# Send an 'enter'
- output += self._send_command_timing_str(*new_args, **kwargs)
+ output += self._send_command_timing_str(*second_args, **kwargs)
# WLC has excessive delay after this appears on screen
if "802.11b Advanced Configuration" in output:
@@ -770,34 +829,6 @@ Methods
return output
-def send_command_w_yes(self, *args, **kwargs)
-
For 'show interface summary' Cisco WLC adds a -'Would you like to display the next 15 entries?' message -Even though pagination is disabled -Arguments are the same as send_command_timing() method
def send_command_w_yes(self, *args: Any, **kwargs: Any) -> str:
- """
- For 'show interface summary' Cisco WLC adds a
- 'Would you like to display the next 15 entries?' message
- Even though pagination is disabled
- Arguments are the same as send_command_timing() method
- """
- output = self._send_command_timing_str(*args, **kwargs)
- if "(y/n)" in output:
- output += self._send_command_timing_str("y")
- strip_prompt = kwargs.get("strip_prompt", True)
- if strip_prompt:
- # Had to strip trailing prompt twice.
- output = self.strip_prompt(output)
- output = self.strip_prompt(output)
- return output
-
def session_preparation(self)
exit_config_mode
save_config
send_command_w_enter
send_command_w_yes
session_preparation
special_login_handler
netmiko.cisco.cisco_xr
+def set_base_prompt(self, pri_prompt_terminator='#', alt_prompt_terminator='>', delay_factor=1.0, pattern=None)
+
Cisco IOS-XR abbreviates the prompt at 31-chars in config mode.
+Consequently, abbreviate the base_prompt
def set_base_prompt(
+ self,
+ pri_prompt_terminator: str = "#",
+ alt_prompt_terminator: str = ">",
+ delay_factor: float = 1.0,
+ pattern: Optional[str] = None,
+) -> str:
+ """
+ Cisco IOS-XR abbreviates the prompt at 31-chars in config mode.
+
+ Consequently, abbreviate the base_prompt
+ """
+ base_prompt = super().set_base_prompt(
+ pri_prompt_terminator=pri_prompt_terminator,
+ alt_prompt_terminator=alt_prompt_terminator,
+ delay_factor=delay_factor,
+ pattern=pattern,
+ )
+ self.base_prompt = base_prompt[:31]
+ return self.base_prompt
+send_command_timing
send_config_from_file
send_multiline
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
send_config_set
send_multiline
session_preparation
set_base_prompt
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
send_config_set
send_multiline
session_preparation
set_base_prompt
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
save_config
send_config_set
session_preparation
set_base_prompt
+def set_base_prompt(self, pri_prompt_terminator='#', alt_prompt_terminator='>', delay_factor=1.0, pattern=None)
+
Cisco IOS/IOS-XE abbreviates the prompt at 20-chars in config mode.
+Consequently, abbreviate the base_prompt
def set_base_prompt(
+ self,
+ pri_prompt_terminator: str = "#",
+ alt_prompt_terminator: str = ">",
+ delay_factor: float = 1.0,
+ pattern: Optional[str] = None,
+) -> str:
+ """
+ Cisco IOS/IOS-XE abbreviates the prompt at 20-chars in config mode.
+
+ Consequently, abbreviate the base_prompt
+ """
+ base_prompt = super().set_base_prompt(
+ pri_prompt_terminator=pri_prompt_terminator,
+ alt_prompt_terminator=alt_prompt_terminator,
+ delay_factor=delay_factor,
+ pattern=pattern,
+ )
+ self.base_prompt = base_prompt[:16]
+ return self.base_prompt
+send_config_from_file
send_config_set
send_multiline
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
send_config_set
send_multiline
session_preparation
set_base_prompt
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
send_config_set
send_multiline
session_preparation
set_base_prompt
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
send_config_set
send_multiline
session_preparation
set_base_prompt
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
-def check_config_mode(self, check_string=')#', pattern='#')
+def check_config_mode(self, check_string=')#', pattern='[>#]')
Checks if the device is in configuration mode or not.
def check_config_mode(self, check_string: str = ")#", pattern: str = "#") -> bool:
+def check_config_mode(
+ self, check_string: str = ")#", pattern: str = r"[>#]"
+) -> bool:
"""Checks if the device is in configuration mode or not."""
return super().check_config_mode(check_string=check_string, pattern=pattern)
For 'show run-config' Cisco WLC adds a 'Press Enter to continue…' message -Even though pagination is disabled -show run-config also has excessive delays in the output which requires special -handling. -Arguments are the same as send_command_timing() method
show run-config also has excessive delays in the output which requires special +handling.
+Arguments are the same as send_command_timing() method.
def send_command_w_enter(self, *args: Any, **kwargs: Any) -> str:
"""
For 'show run-config' Cisco WLC adds a 'Press Enter to continue...' message
- Even though pagination is disabled
+ Even though pagination is disabled.
+
show run-config also has excessive delays in the output which requires special
handling.
- Arguments are the same as send_command_timing() method
+
+ Arguments are the same as send_command_timing() method.
"""
if len(args) > 1:
raise ValueError("Must pass in delay_factor as keyword argument")
@@ -3641,17 +3727,18 @@ Methods
kwargs["delay_factor"] = self.select_delay_factor(delay_factor)
output = self._send_command_timing_str(*args, **kwargs)
+ second_args = list(args)
+ if len(args) == 1:
+ second_args[0] = self.RETURN
+ else:
+ kwargs["command_string"] = self.RETURN
+ if not kwargs.get("max_loops"):
+ kwargs["max_loops"] = 150
+
if "Press any key" in output or "Press Enter to" in output:
- new_args = list(args)
- if len(args) == 1:
- new_args[0] = self.RETURN
- else:
- kwargs["command_string"] = self.RETURN
- if not kwargs.get("max_loops"):
- kwargs["max_loops"] = 150
# Send an 'enter'
- output += self._send_command_timing_str(*new_args, **kwargs)
+ output += self._send_command_timing_str(*second_args, **kwargs)
# WLC has excessive delay after this appears on screen
if "802.11b Advanced Configuration" in output:
@@ -3678,34 +3765,6 @@ Methods
return output
-def send_command_w_yes(self, *args, **kwargs)
-
For 'show interface summary' Cisco WLC adds a -'Would you like to display the next 15 entries?' message -Even though pagination is disabled -Arguments are the same as send_command_timing() method
def send_command_w_yes(self, *args: Any, **kwargs: Any) -> str:
- """
- For 'show interface summary' Cisco WLC adds a
- 'Would you like to display the next 15 entries?' message
- Even though pagination is disabled
- Arguments are the same as send_command_timing() method
- """
- output = self._send_command_timing_str(*args, **kwargs)
- if "(y/n)" in output:
- output += self._send_command_timing_str("y")
- strip_prompt = kwargs.get("strip_prompt", True)
- if strip_prompt:
- # Had to strip trailing prompt twice.
- output = self.strip_prompt(output)
- output = self.strip_prompt(output)
- return output
-
def session_preparation(self)
send_config_set
send_multiline
session_preparation
set_base_prompt
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
send_config_set
send_multiline
session_preparation
set_base_prompt
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
save_config
session_preparation
+set_base_prompt
exit_config_mode
save_config
send_command_w_enter
send_command_w_yes
session_preparation
special_login_handler
netmiko.cisco_base_connection
def cleanup(self, command: str = "exit") -> None:
"""Gracefully exit the SSH session."""
try:
- # The pattern="" forces use of send_command_timing
- if self.check_config_mode(pattern=""):
+ if self.check_config_mode():
self.exit_config_mode()
except Exception:
pass
@@ -734,7 +731,7 @@ Methods
-def enable(self, cmd='enable', pattern='ssword', enable_pattern=None, re_flags=)
+def enable(self, cmd='enable', pattern='ssword', enable_pattern=None, re_flags=re.IGNORECASE)
Enter enable mode.
diff --git a/docs/netmiko/dell/dell_isilon_ssh.html b/docs/netmiko/dell/dell_isilon_ssh.html
index 97f892aa0..27a5881f9 100644
--- a/docs/netmiko/dell/dell_isilon_ssh.html
+++ b/docs/netmiko/dell/dell_isilon_ssh.html
@@ -362,7 +362,7 @@ Methods
-def config_mode(self, config_command='sudo su', pattern='ssword', re_flags=)
+def config_mode(self, config_command='sudo su', pattern='ssword', re_flags=re.IGNORECASE)
Use equivalent enable method.
diff --git a/docs/netmiko/dell/index.html b/docs/netmiko/dell/index.html
index fb4385e7d..59e1a7d1d 100644
--- a/docs/netmiko/dell/index.html
+++ b/docs/netmiko/dell/index.html
@@ -849,7 +849,7 @@ Methods
-def config_mode(self, config_command='sudo su', pattern='ssword', re_flags=)
+def config_mode(self, config_command='sudo su', pattern='ssword', re_flags=re.IGNORECASE)
Use equivalent enable method.
diff --git a/docs/netmiko/extreme/extreme_exos.html b/docs/netmiko/extreme/extreme_exos.html
index 17a149b9a..c8295b8dc 100644
--- a/docs/netmiko/extreme/extreme_exos.html
+++ b/docs/netmiko/extreme/extreme_exos.html
@@ -40,7 +40,7 @@ Module netmiko.extreme.extreme_exos
"""
def session_preparation(self) -> None:
- self._test_channel_read(pattern=r"#")
+ self._test_channel_read(pattern=r"[>\#]")
self.set_base_prompt()
self.disable_paging(command="disable clipaging")
self.send_command_timing("disable cli prompting")
@@ -371,7 +371,7 @@ Classes
"""
def session_preparation(self) -> None:
- self._test_channel_read(pattern=r"#")
+ self._test_channel_read(pattern=r"[>\#]")
self.set_base_prompt()
self.disable_paging(command="disable clipaging")
self.send_command_timing("disable cli prompting")
diff --git a/docs/netmiko/hp/hp_comware.html b/docs/netmiko/hp/hp_comware.html
index 8d615db8d..1b393cd8a 100644
--- a/docs/netmiko/hp/hp_comware.html
+++ b/docs/netmiko/hp/hp_comware.html
@@ -446,7 +446,7 @@ Methods
-def enable(self, cmd='system-view', pattern='ssword', enable_pattern=None, re_flags=)
+def enable(self, cmd='system-view', pattern='ssword', enable_pattern=None, re_flags=re.IGNORECASE)
enable mode on Comware is system-view.
diff --git a/docs/netmiko/hp/hp_procurve.html b/docs/netmiko/hp/hp_procurve.html
index 3b7d835fb..6dc186452 100644
--- a/docs/netmiko/hp/hp_procurve.html
+++ b/docs/netmiko/hp/hp_procurve.html
@@ -43,13 +43,30 @@ Module netmiko.hp.hp_procurve
# HP output contains VT100 escape codes
self.ansi_escape_codes = True
- # Procurve over SSH uses 'Press any key to continue'
- data = self._test_channel_read(pattern=r"(any key to continue|[>#])")
- if "any key to continue" in data:
- self.write_channel(self.RETURN)
- self._test_channel_read(pattern=r"[>#]")
+ # ProCurve has an odd behavior where the router prompt can show up
+ # before the 'Press any key to continue' message. Read up until the
+ # Copyright banner to get past this.
+ try:
+ self.read_until_pattern(pattern=r".*opyright", read_timeout=1.3)
+ except ReadTimeout:
+ pass
+
+ # Procurve uses 'Press any key to continue'
+ try:
+ data = self.read_until_pattern(
+ pattern=r"(any key to continue|[>#])", read_timeout=3.0
+ )
+ if "any key to continue" in data:
+ self.write_channel(self.RETURN)
+ self.read_until_pattern(pattern=r"[>#]", read_timeout=3.0)
+ except ReadTimeout:
+ pass
self.set_base_prompt()
+ # If prompt still looks odd, try one more time
+ if len(self.base_prompt) >= 25:
+ self.set_base_prompt()
+
self.set_terminal_width(command="terminal width 511", pattern="terminal")
command = self.RETURN + "no page"
self.disable_paging(command=command)
@@ -342,13 +359,30 @@ Classes
# HP output contains VT100 escape codes
self.ansi_escape_codes = True
- # Procurve over SSH uses 'Press any key to continue'
- data = self._test_channel_read(pattern=r"(any key to continue|[>#])")
- if "any key to continue" in data:
- self.write_channel(self.RETURN)
- self._test_channel_read(pattern=r"[>#]")
+ # ProCurve has an odd behavior where the router prompt can show up
+ # before the 'Press any key to continue' message. Read up until the
+ # Copyright banner to get past this.
+ try:
+ self.read_until_pattern(pattern=r".*opyright", read_timeout=1.3)
+ except ReadTimeout:
+ pass
+
+ # Procurve uses 'Press any key to continue'
+ try:
+ data = self.read_until_pattern(
+ pattern=r"(any key to continue|[>#])", read_timeout=3.0
+ )
+ if "any key to continue" in data:
+ self.write_channel(self.RETURN)
+ self.read_until_pattern(pattern=r"[>#]", read_timeout=3.0)
+ except ReadTimeout:
+ pass
self.set_base_prompt()
+ # If prompt still looks odd, try one more time
+ if len(self.base_prompt) >= 25:
+ self.set_base_prompt()
+
self.set_terminal_width(command="terminal width 511", pattern="terminal")
command = self.RETURN + "no page"
self.disable_paging(command=command)
@@ -502,7 +536,7 @@ Methods
-def enable(self, cmd='enable', pattern='password', enable_pattern=None, re_flags=, default_username='manager')
+def enable(self, cmd='enable', pattern='password', enable_pattern=None, re_flags=re.IGNORECASE, default_username='manager')
Enter enable mode
@@ -595,13 +629,30 @@ Methods
# HP output contains VT100 escape codes
self.ansi_escape_codes = True
- # Procurve over SSH uses 'Press any key to continue'
- data = self._test_channel_read(pattern=r"(any key to continue|[>#])")
- if "any key to continue" in data:
- self.write_channel(self.RETURN)
- self._test_channel_read(pattern=r"[>#]")
+ # ProCurve has an odd behavior where the router prompt can show up
+ # before the 'Press any key to continue' message. Read up until the
+ # Copyright banner to get past this.
+ try:
+ self.read_until_pattern(pattern=r".*opyright", read_timeout=1.3)
+ except ReadTimeout:
+ pass
+
+ # Procurve uses 'Press any key to continue'
+ try:
+ data = self.read_until_pattern(
+ pattern=r"(any key to continue|[>#])", read_timeout=3.0
+ )
+ if "any key to continue" in data:
+ self.write_channel(self.RETURN)
+ self.read_until_pattern(pattern=r"[>#]", read_timeout=3.0)
+ except ReadTimeout:
+ pass
self.set_base_prompt()
+ # If prompt still looks odd, try one more time
+ if len(self.base_prompt) >= 25:
+ self.set_base_prompt()
+
self.set_terminal_width(command="terminal width 511", pattern="terminal")
command = self.RETURN + "no page"
self.disable_paging(command=command)
diff --git a/docs/netmiko/huawei/huawei.html b/docs/netmiko/huawei/huawei.html
index cbbc81653..24cbd3df7 100644
--- a/docs/netmiko/huawei/huawei.html
+++ b/docs/netmiko/huawei/huawei.html
@@ -38,7 +38,7 @@ netmiko.huawei.huawei
netmiko.huawei.huawei
def session_preparation(self) -> None:
"""Prepare the session after the connection has been established."""
self.ansi_escape_codes = True
- self._test_channel_read(pattern=r"[>\]]")
+ # The _test_channel_read happens in special_login_handler()
self.set_base_prompt()
self.disable_paging(command="screen-length 0 temporary")
@@ -770,15 +769,14 @@
-def special_login_handler(self, delay_factor=1.0)
-
Handle password change request by ignoring it
def special_login_handler(self, delay_factor: float = 1.0) -> None:
- """Handle password change request by ignoring it"""
-
- # Huawei can prompt for password change. Search for that or for normal prompt
- password_change_prompt = r"((Change now|Please choose))|([\]>]\s*$)"
- output = self.read_until_pattern(password_change_prompt)
- if re.search(password_change_prompt, output):
- self.write_channel("N\n")
- self.clear_buffer()
- return None
-HuaweiBase
:
@@ -851,6 +827,7 @@ session_preparation
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
strip_backspaces
strip_command
session_preparation
set_base_prompt
set_terminal_width
special_login_handler
special_login_handler
strip_ansi_escape_codes
strip_backspaces
strip_command
HuaweiSSH
HuaweiTelnet
-def special_login_handler(self, delay_factor=1.0)
-
Handle password change request by ignoring it
def special_login_handler(self, delay_factor: float = 1.0) -> None:
- """Handle password change request by ignoring it"""
-
- # Huawei can prompt for password change. Search for that or for normal prompt
- password_change_prompt = r"((Change now|Please choose))|([\]>]\s*$)"
- output = self.read_until_pattern(password_change_prompt)
- if re.search(password_change_prompt, output):
- self.write_channel("N\n")
- self.clear_buffer()
- return None
-HuaweiBase
:
@@ -245,6 +222,7 @@ session_preparation
set_base_prompt
set_terminal_width
special_login_handler
strip_ansi_escape_codes
strip_backspaces
strip_command
session_preparation
set_base_prompt
set_terminal_width
special_login_handler
special_login_handler
strip_ansi_escape_codes
strip_backspaces
strip_command
HuaweiSSH
HuaweiSmartAXSSH
netmiko
-def enable(self, cmd='', pattern='ssword', enable_pattern=None, re_flags=)
+def enable(self, cmd='', pattern='ssword', enable_pattern=None, re_flags=re.IGNORECASE)
Enter enable mode.
@@ -4008,7 +4008,7 @@netmiko.juniper.juniper
import re
-import time
import warnings
from typing import Optional, Any
@@ -41,7 +40,10 @@ Module netmiko.juniper.juniper
def session_preparation(self) -> None:
"""Prepare the session after the connection has been established."""
+ pattern = r"[%>$#]"
+ self._test_channel_read(pattern=pattern)
self.enter_cli_mode()
+
cmd = "set cli screen-width 511"
self.set_terminal_width(command=cmd, pattern=r"Screen width set to")
# Overloading disable_paging which is confusing
@@ -62,35 +64,58 @@ Module netmiko.juniper.juniper
"""Return to the Juniper CLI."""
return self._send_command_str("exit", expect_string=r"[#>]")
+ def _determine_mode(self, data: str = "") -> str:
+ """Determine whether in shell or CLI."""
+ pattern = r"[%>$#]"
+ if not data:
+ self.write_channel(self.RETURN)
+ data = self.read_until_pattern(pattern=pattern, read_timeout=10)
+
+ if "%" in data or "$" in data:
+ return "shell"
+ elif ">" in data or "#" in data:
+ return "cli"
+ else:
+ raise ValueError(f"Unexpected data returned for prompt: {data}")
+
def enter_cli_mode(self) -> None:
"""Check if at shell prompt root@ and go into CLI."""
- delay_factor = self.select_delay_factor(delay_factor=0)
- count = 0
- cur_prompt = ""
- while count < 50:
+ mode = self._determine_mode()
+ if mode == "shell":
+ shell_pattern = r"[%$]"
self.write_channel(self.RETURN)
- time.sleep(0.1 * delay_factor)
- cur_prompt = self.read_channel()
+ cur_prompt = self.read_until_pattern(pattern=shell_pattern, read_timeout=10)
if re.search(r"root@", cur_prompt) or re.search(r"^%$", cur_prompt.strip()):
+ cli_pattern = r"[>#]"
self.write_channel("cli" + self.RETURN)
- time.sleep(0.3 * delay_factor)
- self.clear_buffer()
- break
- elif ">" in cur_prompt or "#" in cur_prompt:
- break
- count += 1
+ self.read_until_pattern(pattern=cli_pattern, read_timeout=10)
+ return
- def check_config_mode(self, check_string: str = "]", pattern: str = "") -> bool:
- """Checks if the device is in configuration mode or not."""
- return super().check_config_mode(check_string=check_string)
+ def check_config_mode(
+ self, check_string: str = "]", pattern: str = r"(?m:[>#] $)"
+ ) -> bool:
+ """
+ Checks if the device is in configuration mode or not.
+
+ ?m = Use multiline matching
+
+ Juniper unfortunately will use # as a message indicator when not in config mode
+ For example, with commit confirmed.
+
+ """
+ return super().check_config_mode(check_string=check_string, pattern=pattern)
def config_mode(
self,
config_command: str = "configure",
- pattern: str = r"Entering configuration mode",
+ pattern: str = r"(?s:Entering configuration mode.*\].*#)",
re_flags: int = 0,
) -> str:
- """Enter configuration mode."""
+ """
+ Enter configuration mode.
+
+ ?s = enables re.DOTALL in regex pattern.
+ """
return super().config_mode(
config_command=config_command, pattern=pattern, re_flags=re_flags
)
@@ -101,12 +126,17 @@ Module netmiko.juniper.juniper
"""Exit configuration mode."""
output = ""
if self.check_config_mode():
- output = self._send_command_timing_str(
- exit_config, strip_prompt=False, strip_command=False
+ confirm_msg = "Exit with uncommitted changes"
+ pattern = rf"(?:>|{confirm_msg})"
+ output = self._send_command_str(
+ exit_config,
+ expect_string=pattern,
+ strip_prompt=False,
+ strip_command=False,
)
- if "Exit with uncommitted changes?" in output:
- output += self._send_command_timing_str(
- "yes", strip_prompt=False, strip_command=False
+ if confirm_msg in output:
+ output += self._send_command_str(
+ "yes", expect_string=r">", strip_prompt=False, strip_command=False
)
if self.check_config_mode():
raise ValueError("Failed to exit configuration mode")
@@ -234,8 +264,7 @@ Module netmiko.juniper.juniper
def cleanup(self, command: str = "exit") -> None:
"""Gracefully exit the SSH session."""
try:
- # The pattern="" forces use of send_command_timing
- if self.check_config_mode(pattern=""):
+ if self.check_config_mode():
self.exit_config_mode()
except Exception:
pass
@@ -435,7 +464,10 @@ Classes
def session_preparation(self) -> None:
"""Prepare the session after the connection has been established."""
+ pattern = r"[%>$#]"
+ self._test_channel_read(pattern=pattern)
self.enter_cli_mode()
+
cmd = "set cli screen-width 511"
self.set_terminal_width(command=cmd, pattern=r"Screen width set to")
# Overloading disable_paging which is confusing
@@ -456,35 +488,58 @@ Classes
"""Return to the Juniper CLI."""
return self._send_command_str("exit", expect_string=r"[#>]")
+ def _determine_mode(self, data: str = "") -> str:
+ """Determine whether in shell or CLI."""
+ pattern = r"[%>$#]"
+ if not data:
+ self.write_channel(self.RETURN)
+ data = self.read_until_pattern(pattern=pattern, read_timeout=10)
+
+ if "%" in data or "$" in data:
+ return "shell"
+ elif ">" in data or "#" in data:
+ return "cli"
+ else:
+ raise ValueError(f"Unexpected data returned for prompt: {data}")
+
def enter_cli_mode(self) -> None:
"""Check if at shell prompt root@ and go into CLI."""
- delay_factor = self.select_delay_factor(delay_factor=0)
- count = 0
- cur_prompt = ""
- while count < 50:
+ mode = self._determine_mode()
+ if mode == "shell":
+ shell_pattern = r"[%$]"
self.write_channel(self.RETURN)
- time.sleep(0.1 * delay_factor)
- cur_prompt = self.read_channel()
+ cur_prompt = self.read_until_pattern(pattern=shell_pattern, read_timeout=10)
if re.search(r"root@", cur_prompt) or re.search(r"^%$", cur_prompt.strip()):
+ cli_pattern = r"[>#]"
self.write_channel("cli" + self.RETURN)
- time.sleep(0.3 * delay_factor)
- self.clear_buffer()
- break
- elif ">" in cur_prompt or "#" in cur_prompt:
- break
- count += 1
+ self.read_until_pattern(pattern=cli_pattern, read_timeout=10)
+ return
+
+ def check_config_mode(
+ self, check_string: str = "]", pattern: str = r"(?m:[>#] $)"
+ ) -> bool:
+ """
+ Checks if the device is in configuration mode or not.
+
+ ?m = Use multiline matching
- def check_config_mode(self, check_string: str = "]", pattern: str = "") -> bool:
- """Checks if the device is in configuration mode or not."""
- return super().check_config_mode(check_string=check_string)
+ Juniper unfortunately will use # as a message indicator when not in config mode
+ For example, with commit confirmed.
+
+ """
+ return super().check_config_mode(check_string=check_string, pattern=pattern)
def config_mode(
self,
config_command: str = "configure",
- pattern: str = r"Entering configuration mode",
+ pattern: str = r"(?s:Entering configuration mode.*\].*#)",
re_flags: int = 0,
) -> str:
- """Enter configuration mode."""
+ """
+ Enter configuration mode.
+
+ ?s = enables re.DOTALL in regex pattern.
+ """
return super().config_mode(
config_command=config_command, pattern=pattern, re_flags=re_flags
)
@@ -495,12 +550,17 @@ Classes
"""Exit configuration mode."""
output = ""
if self.check_config_mode():
- output = self._send_command_timing_str(
- exit_config, strip_prompt=False, strip_command=False
+ confirm_msg = "Exit with uncommitted changes"
+ pattern = rf"(?:>|{confirm_msg})"
+ output = self._send_command_str(
+ exit_config,
+ expect_string=pattern,
+ strip_prompt=False,
+ strip_command=False,
)
- if "Exit with uncommitted changes?" in output:
- output += self._send_command_timing_str(
- "yes", strip_prompt=False, strip_command=False
+ if confirm_msg in output:
+ output += self._send_command_str(
+ "yes", expect_string=r">", strip_prompt=False, strip_command=False
)
if self.check_config_mode():
raise ValueError("Failed to exit configuration mode")
@@ -628,8 +688,7 @@ Classes
def cleanup(self, command: str = "exit") -> None:
"""Gracefully exit the SSH session."""
try:
- # The pattern="" forces use of send_command_timing
- if self.check_config_mode(pattern=""):
+ if self.check_config_mode():
self.exit_config_mode()
except Exception:
pass
@@ -650,15 +709,28 @@ Subclasses
Methods
-def check_config_mode(self, check_string=']', pattern='')
+def check_config_mode(self, check_string=']', pattern='(?m:[>#] $)')
-
-
Checks if the device is in configuration mode or not.
+Checks if the device is in configuration mode or not.
+?m = Use multiline matching
+Juniper unfortunately will use # as a message indicator when not in config mode
+For example, with commit confirmed.
Source code
-def check_config_mode(self, check_string: str = "]", pattern: str = "") -> bool:
- """Checks if the device is in configuration mode or not."""
- return super().check_config_mode(check_string=check_string)
+def check_config_mode(
+ self, check_string: str = "]", pattern: str = r"(?m:[>#] $)"
+) -> bool:
+ """
+ Checks if the device is in configuration mode or not.
+
+ ?m = Use multiline matching
+
+ Juniper unfortunately will use # as a message indicator when not in config mode
+ For example, with commit confirmed.
+
+ """
+ return super().check_config_mode(check_string=check_string, pattern=pattern)
@@ -671,8 +743,7 @@ Methods
def cleanup(self, command: str = "exit") -> None:
"""Gracefully exit the SSH session."""
try:
- # The pattern="" forces use of send_command_timing
- if self.check_config_mode(pattern=""):
+ if self.check_config_mode():
self.exit_config_mode()
except Exception:
pass
@@ -792,19 +863,24 @@ Methods
-def config_mode(self, config_command='configure', pattern='Entering configuration mode', re_flags=0)
+def config_mode(self, config_command='configure', pattern='(?s:Entering configuration mode.*\\].*#)', re_flags=0)
Enter configuration mode.
Enter configuration mode.
+?s = enables re.DOTALL in regex pattern.
def config_mode(
self,
config_command: str = "configure",
- pattern: str = r"Entering configuration mode",
+ pattern: str = r"(?s:Entering configuration mode.*\].*#)",
re_flags: int = 0,
) -> str:
- """Enter configuration mode."""
+ """
+ Enter configuration mode.
+
+ ?s = enables re.DOTALL in regex pattern.
+ """
return super().config_mode(
config_command=config_command, pattern=pattern, re_flags=re_flags
)
@@ -819,21 +895,16 @@ def enter_cli_mode(self) -> None:
"""Check if at shell prompt root@ and go into CLI."""
- delay_factor = self.select_delay_factor(delay_factor=0)
- count = 0
- cur_prompt = ""
- while count < 50:
+ mode = self._determine_mode()
+ if mode == "shell":
+ shell_pattern = r"[%$]"
self.write_channel(self.RETURN)
- time.sleep(0.1 * delay_factor)
- cur_prompt = self.read_channel()
+ cur_prompt = self.read_until_pattern(pattern=shell_pattern, read_timeout=10)
if re.search(r"root@", cur_prompt) or re.search(r"^%$", cur_prompt.strip()):
+ cli_pattern = r"[>#]"
self.write_channel("cli" + self.RETURN)
- time.sleep(0.3 * delay_factor)
- self.clear_buffer()
- break
- elif ">" in cur_prompt or "#" in cur_prompt:
- break
- count += 1
+ self.read_until_pattern(pattern=cli_pattern, read_timeout=10)
+ return
@@ -849,12 +920,17 @@ Methods
"""Exit configuration mode."""
output = ""
if self.check_config_mode():
- output = self._send_command_timing_str(
- exit_config, strip_prompt=False, strip_command=False
+ confirm_msg = "Exit with uncommitted changes"
+ pattern = rf"(?:>|{confirm_msg})"
+ output = self._send_command_str(
+ exit_config,
+ expect_string=pattern,
+ strip_prompt=False,
+ strip_command=False,
)
- if "Exit with uncommitted changes?" in output:
- output += self._send_command_timing_str(
- "yes", strip_prompt=False, strip_command=False
+ if confirm_msg in output:
+ output += self._send_command_str(
+ "yes", expect_string=r">", strip_prompt=False, strip_command=False
)
if self.check_config_mode():
raise ValueError("Failed to exit configuration mode")
@@ -870,7 +946,10 @@ Methods
Source code
def session_preparation(self) -> None:
"""Prepare the session after the connection has been established."""
+ pattern = r"[%>$#]"
+ self._test_channel_read(pattern=pattern)
self.enter_cli_mode()
+
cmd = "set cli screen-width 511"
self.set_terminal_width(command=cmd, pattern=r"Screen width set to")
# Overloading disable_paging which is confusing
diff --git a/docs/netmiko/keymile/index.html b/docs/netmiko/keymile/index.html
index 528bda949..3296ce928 100644
--- a/docs/netmiko/keymile/index.html
+++ b/docs/netmiko/keymile/index.html
@@ -245,7 +245,7 @@ Inherited members
send_config_set
send_multiline
session_preparation
-set_base_prompt
+set_base_prompt
set_terminal_width
strip_ansi_escape_codes
strip_backspaces
diff --git a/docs/netmiko/keymile/keymile_nos_ssh.html b/docs/netmiko/keymile/keymile_nos_ssh.html
index 766fb2325..374a69b35 100644
--- a/docs/netmiko/keymile/keymile_nos_ssh.html
+++ b/docs/netmiko/keymile/keymile_nos_ssh.html
@@ -264,7 +264,7 @@ Inherited members
send_config_set
send_multiline
session_preparation
-set_base_prompt
+set_base_prompt
set_terminal_width
strip_ansi_escape_codes
strip_backspaces
diff --git a/docs/netmiko/linux/index.html b/docs/netmiko/linux/index.html
index 4a2afa66d..6fe789b5d 100644
--- a/docs/netmiko/linux/index.html
+++ b/docs/netmiko/linux/index.html
@@ -432,7 +432,7 @@ Methods
-def config_mode(self, config_command='sudo -s', pattern='ssword', re_flags=)
+def config_mode(self, config_command='sudo -s', pattern='ssword', re_flags=re.IGNORECASE)
-
Attempt to become root.
@@ -461,7 +461,7 @@ Methods
-def enable(self, cmd='sudo -s', pattern='ssword', enable_pattern=None, re_flags=)
+def enable(self, cmd='sudo -s', pattern='ssword', enable_pattern=None, re_flags=re.IGNORECASE)
-
Attempt to become root.
diff --git a/docs/netmiko/linux/linux_ssh.html b/docs/netmiko/linux/linux_ssh.html
index 6f2fdc570..25100cdd1 100644
--- a/docs/netmiko/linux/linux_ssh.html
+++ b/docs/netmiko/linux/linux_ssh.html
@@ -627,7 +627,7 @@ Methods
-def config_mode(self, config_command='sudo -s', pattern='ssword', re_flags=)
+def config_mode(self, config_command='sudo -s', pattern='ssword', re_flags=re.IGNORECASE)
-
Attempt to become root.
@@ -656,7 +656,7 @@ Methods
-def enable(self, cmd='sudo -s', pattern='ssword', enable_pattern=None, re_flags=)
+def enable(self, cmd='sudo -s', pattern='ssword', enable_pattern=None, re_flags=re.IGNORECASE)
-
Attempt to become root.
diff --git a/docs/netmiko/mellanox/index.html b/docs/netmiko/mellanox/index.html
index 1576f6efe..b0807fe36 100644
--- a/docs/netmiko/mellanox/index.html
+++ b/docs/netmiko/mellanox/index.html
@@ -248,7 +248,7 @@ Ancestors
Methods
-def enable(self, cmd='enable', pattern='#', enable_pattern=None, re_flags=)
+def enable(self, cmd='enable', pattern='#', enable_pattern=None, re_flags=re.IGNORECASE)
-
Enter into enable mode.
diff --git a/docs/netmiko/mellanox/mellanox_mlnxos_ssh.html b/docs/netmiko/mellanox/mellanox_mlnxos_ssh.html
index 5add9c30e..fd5de7660 100644
--- a/docs/netmiko/mellanox/mellanox_mlnxos_ssh.html
+++ b/docs/netmiko/mellanox/mellanox_mlnxos_ssh.html
@@ -331,7 +331,7 @@ Ancestors
Methods
-def enable(self, cmd='enable', pattern='#', enable_pattern=None, re_flags=)
+def enable(self, cmd='enable', pattern='#', enable_pattern=None, re_flags=re.IGNORECASE)
-
Enter into enable mode.
diff --git a/docs/netmiko/mrv/index.html b/docs/netmiko/mrv/index.html
index 2d7a8c246..9deb65fe5 100644
--- a/docs/netmiko/mrv/index.html
+++ b/docs/netmiko/mrv/index.html
@@ -468,7 +468,7 @@ Ancestors
Methods
-def enable(self, cmd='enable', pattern='#', enable_pattern=None, re_flags=)
+def enable(self, cmd='enable', pattern='#', enable_pattern=None, re_flags=re.IGNORECASE)
-
Enable mode on MRV uses no password.
diff --git a/docs/netmiko/mrv/mrv_ssh.html b/docs/netmiko/mrv/mrv_ssh.html
index ad9682e6d..f28ade8cd 100644
--- a/docs/netmiko/mrv/mrv_ssh.html
+++ b/docs/netmiko/mrv/mrv_ssh.html
@@ -255,7 +255,7 @@ Ancestors
Methods
-def enable(self, cmd='enable', pattern='#', enable_pattern=None, re_flags=)
+def enable(self, cmd='enable', pattern='#', enable_pattern=None, re_flags=re.IGNORECASE)
-
Enable mode on MRV uses no password.
diff --git a/docs/netmiko/no_enable.html b/docs/netmiko/no_enable.html
index 6e122505c..63bc944df 100644
--- a/docs/netmiko/no_enable.html
+++ b/docs/netmiko/no_enable.html
@@ -154,7 +154,7 @@ Methods
-def enable(self, cmd='', pattern='', enable_pattern=None, re_flags=)
+def enable(self, cmd='', pattern='', enable_pattern=None, re_flags=re.IGNORECASE)
-
diff --git a/docs/netmiko/nokia/nokia_sros.html b/docs/netmiko/nokia/nokia_sros.html
index ad7f7f1ac..e8d46e0f4 100644
--- a/docs/netmiko/nokia/nokia_sros.html
+++ b/docs/netmiko/nokia/nokia_sros.html
@@ -24,8 +24,8 @@
Module netmiko.nokia.nokia_sros
Source code
#!/usr/bin/python
# -*- coding: utf-8 -*-
-# Copyright (c) 2014 - 2020 Kirk Byers
-# Copyright (c) 2014 - 2020 Twin Bridges Technology
+# Copyright (c) 2014 - 2022 Kirk Byers
+# Copyright (c) 2014 - 2022 Twin Bridges Technology
# Copyright (c) 2019 - 2020 NOKIA Inc.
# MIT License - See License file at:
# https://github.com/ktbyers/netmiko/blob/develop/LICENSE
@@ -38,6 +38,7 @@ Module netmiko.nokia.nokia_sros
from netmiko import log
from netmiko.base_connection import BaseConnection
from netmiko.scp_handler import BaseFileTransfer
+from netmiko.utilities import nokia_context_filter
class NokiaSros(BaseConnection):
@@ -250,9 +251,13 @@ Module netmiko.nokia.nokia_sros
"""Strip prompt from the output."""
output = super().strip_prompt(*args, **kwargs)
if "@" in self.base_prompt:
- # Remove context prompt too
- strips = r"[\r\n]*\!?\*?(\((ex|gl|pr|ro)\))?\[\S*\][\r\n]*"
- return re.sub(strips, "", output)
+ # Remove Nokia context prompt too
+ output_list = output.rstrip().splitlines()
+ last_line = output_list[-1]
+ other_lines = output_list[:-1]
+ last_line = nokia_context_filter(last_line)
+ output_list = other_lines + [last_line]
+ return "\n".join(output_list).rstrip()
else:
return output
@@ -754,9 +759,13 @@ Classes
"""Strip prompt from the output."""
output = super().strip_prompt(*args, **kwargs)
if "@" in self.base_prompt:
- # Remove context prompt too
- strips = r"[\r\n]*\!?\*?(\((ex|gl|pr|ro)\))?\[\S*\][\r\n]*"
- return re.sub(strips, "", output)
+ # Remove Nokia context prompt too
+ output_list = output.rstrip().splitlines()
+ last_line = output_list[-1]
+ other_lines = output_list[:-1]
+ last_line = nokia_context_filter(last_line)
+ output_list = other_lines + [last_line]
+ return "\n".join(output_list).rstrip()
else:
return output
@@ -894,7 +903,7 @@ Methods
-def enable(self, cmd='enable', pattern='ssword', enable_pattern=None, re_flags=)
+def enable(self, cmd='enable', pattern='ssword', enable_pattern=None, re_flags=re.IGNORECASE)
-
Enable SR OS administrative mode
@@ -1016,9 +1025,13 @@ Methods
"""Strip prompt from the output."""
output = super().strip_prompt(*args, **kwargs)
if "@" in self.base_prompt:
- # Remove context prompt too
- strips = r"[\r\n]*\!?\*?(\((ex|gl|pr|ro)\))?\[\S*\][\r\n]*"
- return re.sub(strips, "", output)
+ # Remove Nokia context prompt too
+ output_list = output.rstrip().splitlines()
+ last_line = output_list[-1]
+ other_lines = output_list[:-1]
+ last_line = nokia_context_filter(last_line)
+ output_list = other_lines + [last_line]
+ return "\n".join(output_list).rstrip()
else:
return output
diff --git a/docs/netmiko/ruckus/ruckus_fastiron.html b/docs/netmiko/ruckus/ruckus_fastiron.html
index 12ac11086..023186b1a 100644
--- a/docs/netmiko/ruckus/ruckus_fastiron.html
+++ b/docs/netmiko/ruckus/ruckus_fastiron.html
@@ -340,7 +340,7 @@ Subclasses
Methods
-def enable(self, cmd='enable', pattern='(ssword|User Name)', enable_pattern=None, re_flags=)
+def enable(self, cmd='enable', pattern='(ssword|User Name)', enable_pattern=None, re_flags=re.IGNORECASE)
-
Enter enable mode.
diff --git a/docs/netmiko/ssh_autodetect.html b/docs/netmiko/ssh_autodetect.html
index 98438505d..6b9969ef3 100644
--- a/docs/netmiko/ssh_autodetect.html
+++ b/docs/netmiko/ssh_autodetect.html
@@ -297,7 +297,7 @@
Netmiko connection creation section
},
"fortinet": {
"cmd": "get system status",
- "search_patterns": [r"FortiOS"],
+ "search_patterns": [r"FortiOS", r"FortiGate"],
"priority": 99,
"dispatch": "_autodetect_std",
},
diff --git a/docs/netmiko/tplink/tplink_jetstream.html b/docs/netmiko/tplink/tplink_jetstream.html
index 18e35708c..f571e7c33 100644
--- a/docs/netmiko/tplink/tplink_jetstream.html
+++ b/docs/netmiko/tplink/tplink_jetstream.html
@@ -492,7 +492,7 @@ Methods
-def enable(self, cmd='', pattern='ssword', enable_pattern=None, re_flags=)
+def enable(self, cmd='', pattern='ssword', enable_pattern=None, re_flags=re.IGNORECASE)
-
TPLink JetStream requires you to first execute "enable" and then execute "enable-admin".
diff --git a/docs/netmiko/ubiquiti/edge_ssh.html b/docs/netmiko/ubiquiti/edge_ssh.html
index 8383cee0a..cfc876d11 100644
--- a/docs/netmiko/ubiquiti/edge_ssh.html
+++ b/docs/netmiko/ubiquiti/edge_ssh.html
@@ -70,13 +70,41 @@
Module netmiko.ubiquiti.edge_ssh
def save_config(
self,
cmd: str = "write memory",
- confirm: bool = False,
- confirm_response: str = "",
+ confirm: bool = True,
+ confirm_response: str = "y",
) -> str:
- """Saves configuration."""
- return super().save_config(
- cmd=cmd, confirm=confirm, confirm_response=confirm_response
- )
+ """
+ EdgeSwitch might do the following:
+
+ Are you sure you want to save? (y/n) y
+
+ It is not clear to me that it always does this (or sometimes doesn't).
+
+ Consequently, save_config() handles both cases.
+ """
+ self.enable()
+ confirm_msg = "Are you sure"
+ pattern = rf"({confirm_msg}|\#)"
+ if confirm:
+ output = self._send_command_str(
+ command_string=cmd,
+ expect_string=pattern,
+ strip_prompt=False,
+ strip_command=False,
+ )
+ if confirm_response and confirm_msg in output:
+ output += self._send_command_str(
+ confirm_response,
+ expect_string=r"\#",
+ strip_prompt=False,
+ strip_command=False,
+ )
+ else:
+ # Shouldn't really be here--but handle base case if someone disables "confirm".
+ output = self._send_command_str(
+ command_string=cmd, strip_prompt=False, strip_command=False
+ )
+ return output
-def save_config(self, cmd='write memory', confirm=False, confirm_response='')
+def save_config(self, cmd='write memory', confirm=True, confirm_response='y')
Saves configuration.
EdgeSwitch might do the following:
+Are you sure you want to save? (y/n) y
+It is not clear to me that it always does this (or sometimes doesn't).
+Consequently, save_config() handles both cases.
def save_config(
self,
cmd: str = "write memory",
- confirm: bool = False,
- confirm_response: str = "",
+ confirm: bool = True,
+ confirm_response: str = "y",
) -> str:
- """Saves configuration."""
- return super().save_config(
- cmd=cmd, confirm=confirm, confirm_response=confirm_response
- )
+ """
+ EdgeSwitch might do the following:
+
+ Are you sure you want to save? (y/n) y
+
+ It is not clear to me that it always does this (or sometimes doesn't).
+
+ Consequently, save_config() handles both cases.
+ """
+ self.enable()
+ confirm_msg = "Are you sure"
+ pattern = rf"({confirm_msg}|\#)"
+ if confirm:
+ output = self._send_command_str(
+ command_string=cmd,
+ expect_string=pattern,
+ strip_prompt=False,
+ strip_command=False,
+ )
+ if confirm_response and confirm_msg in output:
+ output += self._send_command_str(
+ confirm_response,
+ expect_string=r"\#",
+ strip_prompt=False,
+ strip_command=False,
+ )
+ else:
+ # Shouldn't really be here--but handle base case if someone disables "confirm".
+ output = self._send_command_str(
+ command_string=cmd, strip_prompt=False, strip_command=False
+ )
+ return output
-def save_config(self, cmd='save', confirm=False, confirm_response='')
-
Saves Config.
def save_config(
- self, cmd: str = "save", confirm: bool = False, confirm_response: str = ""
-) -> str:
- """Saves Config."""
- if confirm is True:
- raise ValueError("EdgeRouter does not support save_config confirmation.")
- output = self._send_command_str(command_string=cmd)
- if "Done" not in output:
- raise ValueError(f"Save failed with following errors:\n\n{output}")
- return output
-VyOSSSH
:
@@ -252,6 +230,7 @@ read_until_prompt
read_until_prompt_or_pattern
run_ttp
save_config
select_delay_factor
send_command
send_command_expect
-def save_config(self, cmd='save', confirm=False, confirm_response='')
-
Saves Config.
def save_config(
- self, cmd: str = "save", confirm: bool = False, confirm_response: str = ""
-) -> str:
- """Saves Config."""
- if confirm is True:
- raise ValueError("EdgeRouter does not support save_config confirmation.")
- output = self._send_command_str(command_string=cmd)
- if "Done" not in output:
- raise ValueError(f"Save failed with following errors:\n\n{output}")
- return output
-VyOSSSH
:
@@ -249,6 +227,7 @@ read_until_prompt
read_until_prompt_or_pattern
run_ttp
save_config
select_delay_factor
send_command
send_command_expect
-def save_config(self, cmd='write memory', confirm=False, confirm_response='')
+def save_config(self, cmd='write memory', confirm=True, confirm_response='y')
Saves configuration.
EdgeSwitch might do the following:
+Are you sure you want to save? (y/n) y
+It is not clear to me that it always does this (or sometimes doesn't).
+Consequently, save_config() handles both cases.
def save_config(
self,
cmd: str = "write memory",
- confirm: bool = False,
- confirm_response: str = "",
+ confirm: bool = True,
+ confirm_response: str = "y",
) -> str:
- """Saves configuration."""
- return super().save_config(
- cmd=cmd, confirm=confirm, confirm_response=confirm_response
- )
+ """
+ EdgeSwitch might do the following:
+
+ Are you sure you want to save? (y/n) y
+
+ It is not clear to me that it always does this (or sometimes doesn't).
+
+ Consequently, save_config() handles both cases.
+ """
+ self.enable()
+ confirm_msg = "Are you sure"
+ pattern = rf"({confirm_msg}|\#)"
+ if confirm:
+ output = self._send_command_str(
+ command_string=cmd,
+ expect_string=pattern,
+ strip_prompt=False,
+ strip_command=False,
+ )
+ if confirm_response and confirm_msg in output:
+ output += self._send_command_str(
+ confirm_response,
+ expect_string=r"\#",
+ strip_prompt=False,
+ strip_command=False,
+ )
+ else:
+ # Shouldn't really be here--but handle base case if someone disables "confirm".
+ output = self._send_command_str(
+ command_string=cmd, strip_prompt=False, strip_command=False
+ )
+ return output
UbiquitiEdgeRouterSSH
save_config
UbiquitiEdgeSSH
netmiko.utilities
netmiko.utilities
netmiko.utilities
netmiko.utilities
netmiko.utilities
+def nokia_context_filter(data, re_flags=re.MULTILINE)
+
Nokia context from string. Examples:
+(ro)[]
+(ex)[configure router "Base" bgp]
+Converted over to a standalone function for easier unit testing.
def nokia_context_filter(data: str, re_flags: int = re.M) -> str:
+ """
+ Nokia context from string. Examples:
+
+ (ro)[]
+
+ (ex)[configure router "Base" bgp]
+
+ Converted over to a standalone function for easier unit testing.
+ """
+ context_pattern = r"^\!?\*?(\((ex|gl|pr|ro)\))?\[.*\]"
+ return re.sub(context_pattern, "", data, flags=re_flags)
+
def obtain_all_devices(my_devices)
load_devices
load_yaml_file
m_exec_time
nokia_context_filter
obtain_all_devices
obtain_netmiko_filename
run_ttp_template
-def save_config(self, cmd='copy running-config startup-config', confirm=False, confirm_response='')
-
Not Implemented
def save_config(
- self,
- cmd: str = "copy running-config startup-config",
- confirm: bool = False,
- confirm_response: str = "",
-) -> str:
- """Not Implemented"""
- raise NotImplementedError
-
def send_config_set(self, config_commands=None, exit_config_mode=False, **kwargs)
read_until_prompt
read_until_prompt_or_pattern
run_ttp
save_config
select_delay_factor
send_command
send_command_expect
VyOSSSH
check_config_mode
commit
exit_config_mode
-save_config
send_config_set
session_preparation
set_base_prompt
diff --git a/docs/netmiko/vyos/vyos_ssh.html b/docs/netmiko/vyos/vyos_ssh.html
index c7a3b4491..b11ac83d1 100644
--- a/docs/netmiko/vyos/vyos_ssh.html
+++ b/docs/netmiko/vyos/vyos_ssh.html
@@ -155,13 +155,15 @@ Module netmiko.vyos.vyos_ssh
)
def save_config(
- self,
- cmd: str = "copy running-config startup-config",
- confirm: bool = False,
- confirm_response: str = "",
+ self, cmd: str = "save", confirm: bool = False, confirm_response: str = ""
) -> str:
- """Not Implemented"""
- raise NotImplementedError
+ """Saves Config."""
+ output = super().save_config(
+ cmd=cmd, confirm=confirm, confirm_response=confirm_response
+ )
+ if "Done" not in output:
+ raise ValueError(f"Save failed with following errors:\n\n{output}")
+ return output
-def save_config(self, cmd='copy running-config startup-config', confirm=False, confirm_response='')
-
Not Implemented
def save_config(
- self,
- cmd: str = "copy running-config startup-config",
- confirm: bool = False,
- confirm_response: str = "",
-) -> str:
- """Not Implemented"""
- raise NotImplementedError
-
def send_config_set(self, config_commands=None, exit_config_mode=False, **kwargs)
read_until_prompt
read_until_prompt_or_pattern
run_ttp
save_config
select_delay_factor
send_command
send_command_expect
check_config_mode
commit
exit_config_mode
save_config
send_config_set
session_preparation
set_base_prompt