Mini Shell
"""Netmiko Cisco WLC support."""
import time
import re
import socket
from netmiko.ssh_exception import NetmikoAuthenticationException
from netmiko.base_connection import BaseConnection
class CiscoWlcSSH(BaseConnection):
"""Netmiko Cisco WLC support."""
def __init__(self, *args, **kwargs):
# WLC/AireOS has an issue where you can get "No Existing Session" with
# the default conn_timeout (so increase conn_timeout to 10-seconds).
kwargs.setdefault("conn_timeout", 10)
return super().__init__(*args, **kwargs)
def special_login_handler(self, delay_factor=1):
"""WLC presents with the following on login (in certain OS versions)
login as: user
(Cisco Controller)
User: user
Password:****
"""
delay_factor = self.select_delay_factor(delay_factor)
i = 0
time.sleep(delay_factor * 0.5)
output = ""
while i <= 12:
output = self.read_channel()
if output:
if "login as" in output or "User:" in output:
self.write_channel(self.username + self.RETURN)
elif "Password" in output:
self.write_channel(self.password + self.RETURN)
break
time.sleep(delay_factor * 1)
else:
self.write_channel(self.RETURN)
time.sleep(delay_factor * 1.5)
i += 1
def send_command_w_enter(self, *args, **kwargs):
"""
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
"""
if len(args) > 1:
raise ValueError("Must pass in delay_factor as keyword argument")
# If no delay_factor use 1 for default value
delay_factor = kwargs.get("delay_factor", 1)
kwargs["delay_factor"] = self.select_delay_factor(delay_factor)
output = self.send_command_timing(*args, **kwargs)
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(*new_args, **kwargs)
# WLC has excessive delay after this appears on screen
if "802.11b Advanced Configuration" in output:
# Defaults to 30 seconds
time.sleep(kwargs["delay_factor"] * 30)
not_done = True
i = 1
while not_done and i <= 150:
time.sleep(kwargs["delay_factor"] * 3)
i += 1
new_data = ""
new_data = self.read_channel()
if new_data:
output += new_data
else:
not_done = False
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):
"""
Prepare the session after the connection has been established
Cisco WLC uses "config paging disable" to disable paging
"""
self._test_channel_read()
try:
self.set_base_prompt()
except ValueError:
msg = f"Authentication failed: {self.host}"
raise NetmikoAuthenticationException(msg)
self.disable_paging(command="config paging disable")
# Clear the read buffer
time.sleep(0.3 * self.global_delay_factor)
self.clear_buffer()
def cleanup(self, command="logout"):
"""Reset WLC back to normal paging and gracefully close session."""
self.send_command_timing("config paging enable")
# Exit configuration mode
try:
# The pattern="" forces use of send_command_timing
if self.check_config_mode(pattern=""):
self.exit_config_mode()
except Exception:
pass
# End SSH/telnet session
self.write_channel(command + self.RETURN)
count = 0
output = ""
while count <= 5:
time.sleep(0.5)
# The connection might be dead at this point.
try:
output += self.read_channel()
except socket.error:
break
# Don't automatically save the config (user's responsibility)
if "Would you like to save them now" in output:
self._session_log_fin = True
self.write_channel("n" + self.RETURN)
try:
self.write_channel(self.RETURN)
except socket.error:
break
count += 1
def check_config_mode(self, check_string="config", pattern=""):
"""Checks if the device is in configuration mode or not."""
if not pattern:
pattern = re.escape(self.base_prompt)
return super().check_config_mode(check_string, pattern)
def config_mode(self, config_command="config", pattern=""):
"""Enter into config_mode."""
if not pattern:
pattern = re.escape(self.base_prompt)
return super().config_mode(config_command, pattern)
def exit_config_mode(self, exit_config="exit", pattern=""):
"""Exit config_mode."""
if not pattern:
pattern = re.escape(self.base_prompt)
return super().exit_config_mode(exit_config, pattern)
def send_config_set(
self,
config_commands=None,
exit_config_mode=False,
enter_config_mode=False,
**kwargs,
):
return super().send_config_set(
config_commands=config_commands,
exit_config_mode=exit_config_mode,
enter_config_mode=enter_config_mode,
**kwargs,
)
def save_config(self, cmd="save config", confirm=True, confirm_response="y"):
"""Saves Config."""
self.enable()
if confirm:
output = self.send_command_timing(command_string=cmd)
if confirm_response:
output += self.send_command_timing(confirm_response)
else:
# Send enter by default
output += self.send_command_timing(self.RETURN)
else:
# Some devices are slow so match on trailing-prompt if you can
output = self.send_command(command_string=cmd)
return output
Zerion Mini Shell 1.0