[Python-modules-commits] [netmiko] 01/03: Import netmiko_1.1.0.orig.tar.gz
Vincent Bernat
bernat at moszumanska.debian.org
Wed Oct 26 20:17:57 UTC 2016
This is an automated email from the git hooks/post-receive script.
bernat pushed a commit to branch master
in repository netmiko.
commit 9a77bd948e5ccb537016353f5113f6cc59eb40a7
Author: Vincent Bernat <bernat at debian.org>
Date: Wed Oct 26 22:14:53 2016 +0200
Import netmiko_1.1.0.orig.tar.gz
---
PKG-INFO | 2 +-
README.md | 48 +-
VENDOR.md | 15 +-
netmiko.egg-info/PKG-INFO | 2 +-
netmiko.egg-info/SOURCES.txt | 11 +-
netmiko.egg-info/top_level.txt | 2 +
netmiko/__init__.py | 3 +-
netmiko/a10/a10_ssh.py | 7 +-
netmiko/alcatel/alcatel_sros_ssh.py | 22 +-
netmiko/arista/arista_ssh.py | 34 +-
netmiko/aruba/__init__.py | 3 +
netmiko/aruba/aruba_ssh.py | 22 +
netmiko/avaya/avaya_ers_ssh.py | 36 +-
netmiko/avaya/avaya_vsp_ssh.py | 4 +-
netmiko/base_connection.py | 639 +++++++++++++--------
netmiko/brocade/brocade_fastiron_ssh.py | 4 +-
netmiko/brocade/brocade_netiron_ssh.py | 4 +-
netmiko/brocade/brocade_nos_ssh.py | 14 +-
netmiko/cisco/__init__.py | 6 +-
netmiko/cisco/cisco_asa_ssh.py | 42 +-
netmiko/cisco/cisco_ios.py | 22 +
netmiko/cisco/cisco_ios_ssh.py | 5 -
netmiko/cisco/cisco_nxos_ssh.py | 22 +-
netmiko/cisco/cisco_s300.py | 19 +
netmiko/cisco/cisco_wlc_ssh.py | 84 ++-
netmiko/cisco/cisco_xr_ssh.py | 20 +-
...{ssh_connection.py => cisco_base_connection.py} | 36 +-
netmiko/dell/dell_force10_ssh.py | 18 +-
netmiko/enterasys/enterasys_ssh.py | 4 +-
netmiko/extreme/extreme_ssh.py | 4 +-
netmiko/f5/f5_ltm_ssh.py | 9 +-
netmiko/fortinet/fortinet_ssh.py | 72 +--
netmiko/hp/hp_comware_ssh.py | 15 +-
netmiko/hp/hp_procurve_ssh.py | 24 +-
netmiko/huawei/huawei_ssh.py | 13 +-
netmiko/juniper/juniper_ssh.py | 33 +-
netmiko/linux/linux_ssh.py | 35 +-
netmiko/paloalto/paloalto_panos_ssh.py | 20 +-
netmiko/quanta/quanta_mesh_ssh.py | 6 +-
netmiko/scp_handler.py | 142 +++--
netmiko/ssh_dispatcher.py | 12 +
netmiko/utilities.py | 18 +-
netmiko/vyos/__init__.py | 3 +
netmiko/vyos/vyos_ssh.py | 91 +++
setup.py | 6 +-
45 files changed, 1106 insertions(+), 547 deletions(-)
diff --git a/PKG-INFO b/PKG-INFO
index afec092..e518f12 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: netmiko
-Version: 0.5.6
+Version: 1.1.0
Summary: Multi-vendor library to simplify Paramiko SSH connections to network devices
Home-page: https://github.com/ktbyers/netmiko
Author: Kirk Byers
diff --git a/README.md b/README.md
index 3cd0ff1..a95f264 100644
--- a/README.md
+++ b/README.md
@@ -4,27 +4,28 @@ Netmiko
Multi-vendor library to simplify Paramiko SSH connections to network devices
Python 2.6, 2.7, 3.3, 3.4, 3.5
-
+
<br>
#### Requires:
Paramiko >= 1.13+
scp >= 0.10.0
pyyaml
pytest (for unit tests)
-
-
+
+
<br>
#### Supports:
-
+
###### Regularly tested
Arista vEOS
Cisco ASA
Cisco IOS
-Cisco IOS-XE
Cisco IOS-XR
+Cisco SG300
HP Comware7
HP ProCurve
Juniper Junos
+Linux
###### Limited testing
Avaya ERS
@@ -32,32 +33,33 @@ Avaya VSP
Brocade VDX
Brocade ICX/FastIron
Brocade MLX/NetIron
+Cisco IOS-XE
Cisco NX-OS
Cisco WLC
Dell-Force10 DNOS9
Huawei
-Linux
Palo Alto PAN-OS
-
+Vyatta VyOS
+
###### Experimental
A10
-F5 LTM
+Alcatel-Lucent SR-OS
Enterasys
Extreme
+F5 LTM
Fortinet
-Alcatel-Lucent SR-OS
-
+
<br>
## Tutorials:
-##### Standard Tutorial:
+##### Standard Tutorial:
https://pynet.twb-tech.com/blog/automation/netmiko.html
-
-##### SSH Proxy:
+
+##### SSH Proxy:
https://pynet.twb-tech.com/blog/automation/netmiko-proxy.html
-
-
+
+
<br>
## Examples:
@@ -123,8 +125,8 @@ net_connect.exit_enable_mode()
<br>
#### Execute configuration change commands (will automatically enter into config mode)
```py
-config_commands = [ 'logging buffered 20000',
- 'logging buffered 20010',
+config_commands = [ 'logging buffered 20000',
+ 'logging buffered 20010',
'no logging console' ]
output = net_connect.send_config_set(config_commands)
print(output)
@@ -138,8 +140,16 @@ pynet-rtr1(config)#no logging console
pynet-rtr1(config)#end
pynet-rtr1#
```
-
-
+
+## Questions/Discussion
+
+If you find an issue with Netmiko, then you can open an issue on this projects issue page here: [https://github.com/ktbyers/netmiko/issues](https://github.com/ktbyers/netmiko/issues)
+
+If you have questions or would like to discuss Netmiko, a Netmiko channel exists on [this Slack](https://networktocode.slack.com) team. To join, visit [this url](http://slack.networktocode.com/) and request access to the Slack team. Once access is granted you can join the [#netmiko](https://networktocode.slack.com/messages/netmiko/) channel.
+
+
+
+
<br>
---
Kirk Byers
diff --git a/VENDOR.md b/VENDOR.md
index 9bf5c4b..946d260 100644
--- a/VENDOR.md
+++ b/VENDOR.md
@@ -19,14 +19,13 @@ Create a new module for the vendor:
```
$ vi arista_ssh.py
-from netmiko.ssh_connection import SSHConnection
-
-class AristaSSH(SSHConnection):
+from netmiko.cisco_base_connection import CiscoSSHConnection
+class AristaSSH(CiscoSSHConnection):
pass
```
-Inherit from the SSHConnection class. Note, the netmiko package will need to be in
+Inherit from the CiscoSSHConnection class. Note, the netmiko package will need to be in
your PYTHONPATH
Update \_\_init__.py to export the new class:
@@ -74,11 +73,11 @@ def cleanup(self):
def disconnect(self):
```
-As much as possible, you should re-use the inherited methods from SSHConnection
-and BaseSSHConnection (i.e. only re-write what you have to).
+As much as possible, you should re-use the inherited methods from CiscoSSHConnection
+and BaseConnection (i.e. only re-write what you have to).
-BaseSSHConnection is intended to be generic (i.e. irrespective of the vendor)
-SSHConnection is Cisco-IOS specific (because lots of vendors imitate Cisco IOS).
+BaseConnection is intended to be generic (i.e. irrespective of the vendor)
+CiscoSSHConnection is Cisco-IOS specific (because lots of vendors imitate Cisco IOS).
You should also write unit tests and verify the functionality of your new class.
See netmiko/tests/test_cisco_ios.py and netmiko/tests/test_cisco_ios_enable.py.
diff --git a/netmiko.egg-info/PKG-INFO b/netmiko.egg-info/PKG-INFO
index afec092..e518f12 100644
--- a/netmiko.egg-info/PKG-INFO
+++ b/netmiko.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: netmiko
-Version: 0.5.6
+Version: 1.1.0
Summary: Multi-vendor library to simplify Paramiko SSH connections to network devices
Home-page: https://github.com/ktbyers/netmiko
Author: Kirk Byers
diff --git a/netmiko.egg-info/SOURCES.txt b/netmiko.egg-info/SOURCES.txt
index 808d513..163e6e7 100644
--- a/netmiko.egg-info/SOURCES.txt
+++ b/netmiko.egg-info/SOURCES.txt
@@ -8,9 +8,9 @@ setup.cfg
setup.py
netmiko/__init__.py
netmiko/base_connection.py
+netmiko/cisco_base_connection.py
netmiko/netmiko_globals.py
netmiko/scp_handler.py
-netmiko/ssh_connection.py
netmiko/ssh_dispatcher.py
netmiko/ssh_exception.py
netmiko/utilities.py
@@ -25,6 +25,8 @@ netmiko/alcatel/__init__.py
netmiko/alcatel/alcatel_sros_ssh.py
netmiko/arista/__init__.py
netmiko/arista/arista_ssh.py
+netmiko/aruba/__init__.py
+netmiko/aruba/aruba_ssh.py
netmiko/avaya/__init__.py
netmiko/avaya/avaya_ers_ssh.py
netmiko/avaya/avaya_vsp_ssh.py
@@ -34,8 +36,9 @@ netmiko/brocade/brocade_netiron_ssh.py
netmiko/brocade/brocade_nos_ssh.py
netmiko/cisco/__init__.py
netmiko/cisco/cisco_asa_ssh.py
-netmiko/cisco/cisco_ios_ssh.py
+netmiko/cisco/cisco_ios.py
netmiko/cisco/cisco_nxos_ssh.py
+netmiko/cisco/cisco_s300.py
netmiko/cisco/cisco_wlc_ssh.py
netmiko/cisco/cisco_xr_ssh.py
netmiko/dell/__init__.py
@@ -62,4 +65,6 @@ netmiko/ovs/ovs_linux_ssh.py
netmiko/paloalto/__init__.py
netmiko/paloalto/paloalto_panos_ssh.py
netmiko/quanta/__init__.py
-netmiko/quanta/quanta_mesh_ssh.py
\ No newline at end of file
+netmiko/quanta/quanta_mesh_ssh.py
+netmiko/vyos/__init__.py
+netmiko/vyos/vyos_ssh.py
\ No newline at end of file
diff --git a/netmiko.egg-info/top_level.txt b/netmiko.egg-info/top_level.txt
index b80e31b..a9fee05 100644
--- a/netmiko.egg-info/top_level.txt
+++ b/netmiko.egg-info/top_level.txt
@@ -2,6 +2,7 @@ netmiko
netmiko/a10
netmiko/alcatel
netmiko/arista
+netmiko/aruba
netmiko/avaya
netmiko/brocade
netmiko/cisco
@@ -17,3 +18,4 @@ netmiko/linux
netmiko/ovs
netmiko/paloalto
netmiko/quanta
+netmiko/vyos
diff --git a/netmiko/__init__.py b/netmiko/__init__.py
index 069c2fb..ba155d0 100644
--- a/netmiko/__init__.py
+++ b/netmiko/__init__.py
@@ -10,7 +10,8 @@ from netmiko.ssh_exception import NetMikoAuthenticationException
NetmikoTimeoutError = NetMikoTimeoutException
NetmikoAuthError = NetMikoAuthenticationException
-__version__ = '0.5.6'
+__version__ = '1.1.0'
+
__all__ = ('ConnectHandler', 'ssh_dispatcher', 'platforms', 'SCPConn', 'FileTransfer',
'NetMikoTimeoutException', 'NetMikoAuthenticationException',
'NetmikoTimeoutError', 'NetmikoAuthError')
diff --git a/netmiko/a10/a10_ssh.py b/netmiko/a10/a10_ssh.py
index 11ab9ae..c89e029 100644
--- a/netmiko/a10/a10_ssh.py
+++ b/netmiko/a10/a10_ssh.py
@@ -1,11 +1,14 @@
"""A10 support."""
-from netmiko.ssh_connection import SSHConnection
+from netmiko.cisco_base_connection import CiscoSSHConnection
-class A10SSH(SSHConnection):
+class A10SSH(CiscoSSHConnection):
"""A10 support."""
def session_preparation(self):
"""A10 requires to be enable mode to disable paging."""
self.set_base_prompt()
self.enable()
self.disable_paging(command="terminal length 0\n")
+
+ # Will not do anything without A10 specific command
+ self.set_terminal_width()
diff --git a/netmiko/alcatel/alcatel_sros_ssh.py b/netmiko/alcatel/alcatel_sros_ssh.py
index ea436ce..fa8e299 100644
--- a/netmiko/alcatel/alcatel_sros_ssh.py
+++ b/netmiko/alcatel/alcatel_sros_ssh.py
@@ -1,9 +1,11 @@
"""Alcatel-Lucent SROS support."""
+from __future__ import print_function
+from __future__ import unicode_literals
import re
-from netmiko.ssh_connection import SSHConnection
+from netmiko.cisco_base_connection import CiscoSSHConnection
-class AlcatelSrosSSH(SSHConnection):
+class AlcatelSrosSSH(CiscoSSHConnection):
"""Alcatel-Lucent SROS support."""
def session_preparation(self):
self.set_base_prompt()
@@ -21,5 +23,17 @@ class AlcatelSrosSSH(SSHConnection):
def enable(self, *args, **kwargs):
pass
- def config_mode(self, *args, **kwargs):
- pass
+ def config_mode(self, config_command='configure', pattern='#'):
+ """ Enter into configuration mode on SROS device."""
+ return super(AlcatelSrosSSH, self).config_mode(config_command=config_command,
+ pattern=pattern)
+
+ def exit_config_mode(self, exit_config='exit all', pattern='#'):
+ """ Exit from configuration mode."""
+ return super(AlcatelSrosSSH, self).exit_config_mode(exit_config=exit_config,
+ pattern=pattern)
+
+ def check_config_mode(self, check_string='config', pattern='#'):
+ """ Checks if the device is in configuration mode or not. """
+ return super(AlcatelSrosSSH, self).check_config_mode(check_string=check_string,
+ pattern=pattern)
diff --git a/netmiko/arista/arista_ssh.py b/netmiko/arista/arista_ssh.py
index ef47c09..0708a32 100644
--- a/netmiko/arista/arista_ssh.py
+++ b/netmiko/arista/arista_ssh.py
@@ -1,11 +1,41 @@
+from __future__ import unicode_literals
import time
-from netmiko.ssh_connection import SSHConnection
+from netmiko.cisco_base_connection import CiscoSSHConnection
-class AristaSSH(SSHConnection):
+class AristaSSH(CiscoSSHConnection):
+ def session_preparation(self):
+ """Prepare the session after the connection has been established."""
+ self.set_base_prompt()
+ self.disable_paging()
+ self.set_terminal_width(command='terminal width 511')
+
def special_login_handler(self, delay_factor=1):
"""
Arista adds a "Last login: " message that doesn't always have sufficient time to be handled
"""
+ delay_factor = self.select_delay_factor(delay_factor)
time.sleep(3 * delay_factor)
self.clear_buffer()
+
+ def check_config_mode(self, check_string=')#', pattern=''):
+ """
+ Checks if the device is in configuration mode or not.
+
+ Arista, unfortunately, does this:
+ loc1-core01(s1)#
+
+ Can also be (s2)
+ """
+ debug = False
+ if debug:
+ print("pattern: {}".format(pattern))
+ self.write_channel('\n')
+ output = self.read_until_pattern(pattern=pattern)
+ if debug:
+ print("check_config_mode: {}".format(repr(output)))
+ output = output.replace("(s1)", "")
+ output = output.replace("(s2)", "")
+ if debug:
+ print("check_config_mode: {}".format(repr(output)))
+ return check_string in output
diff --git a/netmiko/aruba/__init__.py b/netmiko/aruba/__init__.py
new file mode 100644
index 0000000..cc71d05
--- /dev/null
+++ b/netmiko/aruba/__init__.py
@@ -0,0 +1,3 @@
+from netmiko.aruba.aruba_ssh import ArubaSSH
+
+__all__ = ['ArubaSSH']
diff --git a/netmiko/aruba/aruba_ssh.py b/netmiko/aruba/aruba_ssh.py
new file mode 100644
index 0000000..092a363
--- /dev/null
+++ b/netmiko/aruba/aruba_ssh.py
@@ -0,0 +1,22 @@
+"""Aruba OS support"""
+from netmiko.cisco_base_connection import CiscoSSHConnection
+
+
+class ArubaSSH(CiscoSSHConnection):
+ """Aruba OS support"""
+ def session_preparation(self):
+ """Aruba OS requires enable mode to disable paging."""
+ self.set_base_prompt()
+ self.enable()
+ self.disable_paging(command="no paging")
+
+ def check_config_mode(self, check_string='(config) #', pattern=''):
+ """
+ Checks if the device is in configuration mode or not.
+
+ Aruba uses "(<controller name>) (config) #" as config prompt
+ """
+ if not pattern:
+ pattern = self.base_prompt[:16]
+ return super(ArubaSSH, self).check_config_mode(check_string=check_string,
+ pattern=pattern)
diff --git a/netmiko/avaya/avaya_ers_ssh.py b/netmiko/avaya/avaya_ers_ssh.py
index b3f65dc..1fcc35f 100644
--- a/netmiko/avaya/avaya_ers_ssh.py
+++ b/netmiko/avaya/avaya_ers_ssh.py
@@ -1,42 +1,38 @@
-'''
-Netmiko support for Avaya Ethernet Routing Switch
-'''
+"""Netmiko support for Avaya Ethernet Routing Switch."""
from __future__ import print_function
from __future__ import unicode_literals
-from netmiko.ssh_connection import SSHConnection
-from netmiko.netmiko_globals import MAX_BUFFER
import time
+from netmiko.cisco_base_connection import CiscoSSHConnection
# Avaya presents Enter Ctrl-Y to begin.
CTRL_Y = '\x19'
-class AvayaErsSSH(SSHConnection):
- '''
- Netmiko support for Avaya Ethernet Routing Switch
- '''
- def special_login_handler(self, delay_factor=.5):
- '''
+class AvayaErsSSH(CiscoSSHConnection):
+ """Netmiko support for Avaya Ethernet Routing Switch."""
+ def special_login_handler(self, delay_factor=1):
+ """
Avaya ERS presents the following as part of the login process:
Enter Ctrl-Y to begin.
- '''
+ """
delay_factor = self.select_delay_factor(delay_factor)
# Handle 'Enter Ctrl-Y to begin'
+ output = ""
i = 0
while i <= 12:
- if self.remote_conn.recv_ready():
- output = self.remote_conn.recv(MAX_BUFFER).decode('utf-8', 'ignore')
+ output = self.read_channel()
+ if output:
if 'Ctrl-Y' in output:
- self.remote_conn.sendall(CTRL_Y)
+ self.write_channel(CTRL_Y)
if 'sername' in output:
- self.remote_conn.sendall(self.username + '\n')
+ self.write_channel(self.username + '\n')
elif 'ssword' in output:
- self.remote_conn.sendall(self.password + '\n')
+ self.write_channel(self.password + '\n')
break
- time.sleep(delay_factor)
+ time.sleep(.5 * delay_factor)
else:
- self.remote_conn.sendall('\n')
- time.sleep(2 * delay_factor)
+ self.write_channel('\n')
+ time.sleep(1 * delay_factor)
i += 1
diff --git a/netmiko/avaya/avaya_vsp_ssh.py b/netmiko/avaya/avaya_vsp_ssh.py
index 777abba..ad91f4a 100644
--- a/netmiko/avaya/avaya_vsp_ssh.py
+++ b/netmiko/avaya/avaya_vsp_ssh.py
@@ -1,10 +1,10 @@
"""Avaya Virtual Services Platform Support."""
from __future__ import print_function
from __future__ import unicode_literals
-from netmiko.ssh_connection import SSHConnection
+from netmiko.cisco_base_connection import CiscoSSHConnection
-class AvayaVspSSH(SSHConnection):
+class AvayaVspSSH(CiscoSSHConnection):
"""Avaya Virtual Services Platform Support."""
def session_preparation(self):
"""Prepare the session after the connection has been established."""
diff --git a/netmiko/base_connection.py b/netmiko/base_connection.py
index de2f10c..e40a2db 100644
--- a/netmiko/base_connection.py
+++ b/netmiko/base_connection.py
@@ -11,6 +11,7 @@ from __future__ import print_function
from __future__ import unicode_literals
import paramiko
+import telnetlib
import time
import socket
import re
@@ -19,18 +20,19 @@ from os import path
from netmiko.netmiko_globals import MAX_BUFFER, BACKSPACE_CHAR
from netmiko.ssh_exception import NetMikoTimeoutException, NetMikoAuthenticationException
+from netmiko.utilities import write_bytes
-class BaseSSHConnection(object):
+class BaseConnection(object):
"""
Defines vendor independent methods.
Otherwise method left as a stub method.
"""
- def __init__(self, ip=u'', host=u'', username=u'', password=u'', secret=u'', port=22,
- device_type=u'', verbose=False, global_delay_factor=.1, use_keys=False,
- key_file=None, ssh_strict=False, system_host_keys=False, alt_host_keys=False,
- alt_key_file='', ssh_config_file=None):
+ def __init__(self, ip='', host='', username='', password='', secret='', port=None,
+ device_type='', verbose=False, global_delay_factor=1, use_keys=False,
+ key_file=None, allow_agent=False, ssh_strict=False, system_host_keys=False,
+ alt_host_keys=False, alt_key_file='', ssh_config_file=None, timeout=8):
if ip:
self.host = ip
@@ -39,12 +41,20 @@ class BaseSSHConnection(object):
self.host = host
if not ip and not host:
raise ValueError("Either ip or host must be set")
- self.port = int(port)
+ if port is None:
+ if 'telnet' in device_type:
+ self.port = 23
+ else:
+ self.port = 22
+ else:
+ self.port = int(port)
self.username = username
self.password = password
self.secret = secret
self.device_type = device_type
self.ansi_escape_codes = False
+ self.verbose = verbose
+ self.timeout = timeout
# Use the greater of global_delay_factor or delay_factor local to method
self.global_delay_factor = global_delay_factor
@@ -52,21 +62,222 @@ class BaseSSHConnection(object):
# set in set_base_prompt method
self.base_prompt = ''
- if not ssh_strict:
- self.key_policy = paramiko.AutoAddPolicy()
+ # determine if telnet or SSH
+ if '_telnet' in device_type:
+ self.protocol = 'telnet'
+ self.establish_connection()
+ self.session_preparation()
+ else:
+ self.protocol = 'ssh'
+
+ if not ssh_strict:
+ self.key_policy = paramiko.AutoAddPolicy()
+ else:
+ self.key_policy = paramiko.RejectPolicy()
+
+ # Options for SSH host_keys
+ self.use_keys = use_keys
+ self.key_file = key_file
+ self.allow_agent = allow_agent
+ self.system_host_keys = system_host_keys
+ self.alt_host_keys = alt_host_keys
+ self.alt_key_file = alt_key_file
+
+ # For SSH proxy support
+ self.ssh_config_file = ssh_config_file
+
+ self.establish_connection()
+ self.session_preparation()
+
+ # Clear the read buffer
+ time.sleep(.3 * self.global_delay_factor)
+ self.clear_buffer()
+
+ def write_channel(self, out_data):
+ """Generic handler that will write to both SSH and telnet channel."""
+ if self.protocol == 'ssh':
+ self.remote_conn.sendall(write_bytes(out_data))
+ elif self.protocol == 'telnet':
+ self.remote_conn.write(write_bytes(out_data))
else:
- self.key_policy = paramiko.RejectPolicy()
+ raise ValueError("Invalid protocol specified")
+
+ def read_channel(self):
+ """Generic handler that will read all the data from an SSH or telnet channel."""
+ if self.protocol == 'ssh':
+ output = ""
+ while True:
+ if self.remote_conn.recv_ready():
+ output += self.remote_conn.recv(MAX_BUFFER).decode('utf-8', 'ignore')
+ else:
+ return output
+ elif self.protocol == 'telnet':
+ return self.remote_conn.read_very_eager().decode('utf-8', 'ignore')
- # Options for SSH host_keys
- self.system_host_keys = system_host_keys
- self.alt_host_keys = alt_host_keys
- self.alt_key_file = alt_key_file
+ def _read_channel_expect(self, pattern='', re_flags=0):
+ """
+ Function that reads channel until pattern is detected.
+
+ pattern takes a regular expression.
+
+ By default pattern will be self.base_prompt
- # For SSH proxy support
- self.ssh_config_file = ssh_config_file
+ Note: this currently reads beyond pattern. In the case of SSH it reads MAX_BUFFER.
+ In the case of telnet it reads all non-blocking data.
- self.establish_connection(verbose=verbose, use_keys=use_keys, key_file=key_file)
- self.session_preparation()
+ There are dependecies here like determining whether in config_mode that are actually
+ depending on reading beyond pattern.
+ """
+ debug = False
+ output = ''
+ if not pattern:
+ pattern = self.base_prompt
+ pattern = re.escape(pattern)
+ if debug:
+ print("Pattern is: {}".format(pattern))
+
+ # Will loop for self.timeout time (unless modified by global_delay_factor)
+ i = 1
+ loop_delay = .1
+ max_loops = self.timeout / loop_delay
+ while i < max_loops:
+ if self.protocol == 'ssh':
+ try:
+ # If no data available will wait timeout seconds trying to read
+ output += self.remote_conn.recv(MAX_BUFFER).decode('utf-8', 'ignore')
+ except socket.timeout:
+ raise NetMikoTimeoutException("Timed-out reading channel, data not available.")
+ elif self.protocol == 'telnet':
+ output += self.read_channel()
+ if re.search(pattern, output, flags=re_flags):
+ if debug:
+ print("Pattern found: {} {}".format(pattern, output))
+ return output
+ time.sleep(loop_delay * self.global_delay_factor)
+ i += 1
+ raise NetMikoTimeoutException("Timed-out reading channel, pattern not found in output: {}"
+ .format(pattern))
+
+ def _read_channel_timing(self, delay_factor=1, max_loops=150):
+ """
+ Read data on the channel based on timing delays.
+
+ Attempt to read channel max_loops number of times. If no data this will cause a 15 second
+ delay.
+
+ Once data is encountered read channel for another two seconds (2 * delay_factor) to make
+ sure reading of channel is complete.
+ """
+ delay_factor = self.select_delay_factor(delay_factor)
+ channel_data = ""
+ i = 0
+ while i <= max_loops:
+ time.sleep(.1 * delay_factor)
+ new_data = self.read_channel()
+ if new_data:
+ channel_data += new_data
+ else:
+ # Safeguard to make sure really done
+ time.sleep(2 * delay_factor)
+ new_data = self.read_channel()
+ if not new_data:
+ break
+ else:
+ channel_data += new_data
+ i += 1
+ return channel_data
+
+ def read_until_prompt(self, *args, **kwargs):
+ """Read channel until self.base_prompt detected. Return ALL data available."""
+ return self._read_channel_expect(*args, **kwargs)
+
+ def read_until_pattern(self, *args, **kwargs):
+ """Read channel until pattern detected. Return ALL data available."""
+ return self._read_channel_expect(*args, **kwargs)
+
+ def read_until_prompt_or_pattern(self, pattern='', re_flags=0):
+ """Read until either self.base_prompt or pattern is detected. Return ALL data available."""
+ output = ''
+ if not pattern:
+ pattern = self.base_prompt
+ pattern = re.escape(pattern)
+ base_prompt_pattern = re.escape(self.base_prompt)
+ while True:
+ try:
+ output += self.read_channel()
+ if re.search(pattern, output, flags=re_flags) or re.search(base_prompt_pattern,
+ output, flags=re_flags):
+ return output
+ except socket.timeout:
+ raise NetMikoTimeoutException("Timed-out reading channel, data not available.")
+
+ def telnet_login(self, pri_prompt_terminator='#', alt_prompt_terminator='>',
+ delay_factor=1, max_loops=60):
+ """Telnet login. Can be username/password or just password."""
+ debug = False
+ if debug:
+ print("In telnet_login():")
+ delay_factor = self.select_delay_factor(delay_factor)
+ time.sleep(1 * delay_factor)
+
+ output = ''
+ return_msg = ''
+ i = 1
+ while i <= max_loops:
+ try:
+ output = self.read_channel()
+ return_msg += output
+ if debug:
+ print(output)
+ if re.search(r"sername", output):
+ self.write_channel(self.username + '\n')
+ time.sleep(1 * delay_factor)
+ output = self.read_channel()
+ return_msg += output
+ if debug:
+ print("checkpoint1")
+ print(output)
+ if re.search(r"assword", output):
+ self.write_channel(self.password + "\n")
+ time.sleep(.5 * delay_factor)
+ output = self.read_channel()
+ return_msg += output
+ if debug:
+ print("checkpoint2")
+ print(output)
+ if pri_prompt_terminator in output or alt_prompt_terminator in output:
+ if debug:
+ print("checkpoint3")
+ return return_msg
+ if re.search(r"assword required, but none set", output):
+ if debug:
+ print("checkpoint4")
+ msg = "Telnet login failed - Password required, but none set: {0}".format(
+ self.host)
+ raise NetMikoAuthenticationException(msg)
+ if pri_prompt_terminator in output or alt_prompt_terminator in output:
+ if debug:
+ print("checkpoint5")
+ return return_msg
+ self.write_channel("\n")
+ time.sleep(.5 * delay_factor)
+ i += 1
+ except EOFError:
+ msg = "Telnet login failed: {0}".format(self.host)
+ raise NetMikoAuthenticationException(msg)
+
+ # Last try to see if we already logged in
+ self.write_channel("\n")
+ time.sleep(.5 * delay_factor)
+ output = self.read_channel()
+ return_msg += output
+ if pri_prompt_terminator in output or alt_prompt_terminator in output:
+ if debug:
+ print("checkpoint6")
+ return return_msg
+
+ msg = "Telnet login failed: {0}".format(self.host)
+ raise NetMikoAuthenticationException(msg)
def session_preparation(self):
"""
@@ -77,10 +288,12 @@ class BaseSSHConnection(object):
In general, it should include:
self.set_base_prompt()
- self.disable_paging() # if applicable
+ self.disable_paging()
+ self.set_terminal_width()
"""
self.set_base_prompt()
self.disable_paging()
+ self.set_terminal_width()
def _use_ssh_config(self, connect_dict):
"""
@@ -116,17 +329,17 @@ class BaseSSHConnection(object):
connect_dict['sock'] = proxy
connect_dict['hostname'] = source.get('hostname', self.host)
- def _connect_params_dict(self, use_keys=False, key_file=None, timeout=8):
+ def _connect_params_dict(self):
"""Convert Paramiko connect params to a dictionary."""
return {
'hostname': self.host,
'port': self.port,
'username': self.username,
'password': self.password,
- 'look_for_keys': use_keys,
- 'allow_agent': False,
- 'key_filename': key_file,
- 'timeout': timeout,
+ 'look_for_keys': self.use_keys,
+ 'allow_agent': self.allow_agent,
+ 'key_filename': self.key_file,
+ 'timeout': self.timeout,
}
def _sanitize_output(self, output, strip_command=False, command_string=None,
@@ -141,64 +354,88 @@ class BaseSSHConnection(object):
output = self.strip_prompt(output)
return output
- def establish_connection(self, sleep_time=3, verbose=True, timeout=8,
- use_keys=False, key_file=None):
+ def establish_connection(self, width=None, height=None):
"""
Establish SSH connection to the network device
Timeout will generate a NetMikoTimeoutException
Authentication failure will generate a NetMikoAuthenticationException
- use_keys is a boolean that allows ssh-keys to be used for authentication
+ width and height are needed for Fortinet paging setting.
"""
+ if self.protocol == 'telnet':
+ self.remote_conn = telnetlib.Telnet(self.host, port=self.port, timeout=self.timeout)
+ self.telnet_login()
+ elif self.protocol == 'ssh':
- # Convert Paramiko connection parameters to a dictionary
- ssh_connect_params = self._connect_params_dict(use_keys=use_keys, key_file=key_file,
- timeout=timeout)
-
- # Check if using SSH 'config' file mainly for SSH proxy support (updates ssh_connect_params)
- if self.ssh_config_file:
- self._use_ssh_config(ssh_connect_params)
-
- # Create instance of SSHClient object
- self.remote_conn_pre = paramiko.SSHClient()
-
- # Load host_keys for better SSH security
- if self.system_host_keys:
- self.remote_conn_pre.load_system_host_keys()
- if self.alt_host_keys and path.isfile(self.alt_key_file):
- self.remote_conn_pre.load_host_keys(self.alt_key_file)
-
- # Default is to automatically add untrusted hosts (make sure appropriate for your env)
- self.remote_conn_pre.set_missing_host_key_policy(self.key_policy)
-
- # initiate SSH connection
- try:
- self.remote_conn_pre.connect(**ssh_connect_params)
- except socket.error:
- msg = "Connection to device timed-out: {device_type} {ip}:{port}".format(
- device_type=self.device_type, ip=self.host, port=self.port)
- raise NetMikoTimeoutException(msg)
- except paramiko.ssh_exception.AuthenticationException as auth_err:
- msg = "Authentication failure: unable to connect {device_type} {ip}:{port}".format(
- device_type=self.device_type, ip=self.host, port=self.port)
- msg += '\n' + str(auth_err)
- raise NetMikoAuthenticationException(msg)
-
- if verbose:
- print("SSH connection established to {0}:{1}".format(self.host, self.port))
-
- # Use invoke_shell to establish an 'interactive session'
- self.remote_conn = self.remote_conn_pre.invoke_shell()
- self.remote_conn.settimeout(timeout)
- self.special_login_handler()
- if verbose:
- print("Interactive SSH session established")
-
- time.sleep(.1)
- if self.wait_for_recv_ready_newline():
- return self.remote_conn.recv(MAX_BUFFER).decode('utf-8', 'ignore')
- return ""
+ # Convert Paramiko connection parameters to a dictionary
+ ssh_connect_params = self._connect_params_dict()
+
+ # Check if using SSH 'config' file mainly for SSH proxy support
+ if self.ssh_config_file:
+ self._use_ssh_config(ssh_connect_params)
+
+ # Create instance of SSHClient object
+ self.remote_conn_pre = paramiko.SSHClient()
+
+ # Load host_keys for better SSH security
+ if self.system_host_keys:
+ self.remote_conn_pre.load_system_host_keys()
+ if self.alt_host_keys and path.isfile(self.alt_key_file):
+ self.remote_conn_pre.load_host_keys(self.alt_key_file)
+
+ # Default is to automatically add untrusted hosts (make sure appropriate for your env)
+ self.remote_conn_pre.set_missing_host_key_policy(self.key_policy)
+
+ # initiate SSH connection
+ try:
+ self.remote_conn_pre.connect(**ssh_connect_params)
+ except socket.error:
+ msg = "Connection to device timed-out: {device_type} {ip}:{port}".format(
+ device_type=self.device_type, ip=self.host, port=self.port)
+ raise NetMikoTimeoutException(msg)
+ except paramiko.ssh_exception.AuthenticationException as auth_err:
+ msg = "Authentication failure: unable to connect {device_type} {ip}:{port}".format(
+ device_type=self.device_type, ip=self.host, port=self.port)
+ msg += '\n' + str(auth_err)
+ raise NetMikoAuthenticationException(msg)
+
+ if self.verbose:
+ print("SSH connection established to {0}:{1}".format(self.host, self.port))
+
+ # Use invoke_shell to establish an 'interactive session'
+ if width and height:
+ self.remote_conn = self.remote_conn_pre.invoke_shell(term='vt100', width=width,
+ height=height)
+ else:
+ self.remote_conn = self.remote_conn_pre.invoke_shell()
+
+ self.remote_conn.settimeout(self.timeout)
+ self.special_login_handler()
+ if self.verbose:
+ print("Interactive SSH session established")
+
+ # make sure you can read the channel
+ i = 0
+ delay_factor = self.select_delay_factor(delay_factor=0)
+ main_delay = delay_factor * .1
+ time.sleep(main_delay)
+ while i <= 40:
+ new_data = self.read_channel()
+ if new_data:
+ break
+ else:
+ self.write_channel('\n')
+ main_delay = main_delay * 1.1
+ if main_delay >= 8:
+ main_delay = 8
+ time.sleep(main_delay)
+ i += 1
+ # check if data was ever present
+ if new_data:
+ return ""
+ else:
+ raise NetMikoTimeoutException("Timed out waiting for data")
def select_delay_factor(self, delay_factor):
"""Choose the greater of delay_factor or self.global_delay_factor."""
@@ -207,20 +444,21 @@ class BaseSSHConnection(object):
else:
return self.global_delay_factor
... 2011 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/netmiko.git
More information about the Python-modules-commits
mailing list