[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