diff --git a/README.md b/README.md
index eda987b9e..cddc92d5b 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 [![PyPI](https://img.shields.io/pypi/v/netmiko.svg)](https://pypi.python.org/pypi/netmiko)
-  
-  
+
+
 Netmiko
 =======
 
@@ -10,70 +10,75 @@ Python 2.7, 3.5, 3.6
 
 #### Requires:
 
-Paramiko >= 2  
-scp >= 0.10.0  
-pyyaml  
-pyserial  
-textfsm  
+- Paramiko >= 2.4.1
+- scp >= 0.10.0
+- pyyaml
+- pyserial
+- textfsm
 
 #### Supports:
 
 ###### Regularly tested
 
-Arista vEOS  
-Cisco ASA  
-Cisco IOS  
-Cisco IOS-XE  
-Cisco IOS-XR  
-Cisco NX-OS  
-Cisco SG300  
-HP Comware7  
-HP ProCurve  
-Juniper Junos  
-Linux  
-  
+- Arista vEOS
+- Cisco ASA
+- Cisco IOS
+- Cisco IOS-XE
+- Cisco IOS-XR
+- Cisco NX-OS
+- Cisco SG300
+- HP Comware7
+- HP ProCurve
+- Juniper Junos
+- Linux
+
 ###### Limited testing
 
-Alcatel AOS6/AOS8  
-Apresia Systems AEOS  
-Avaya ERS  
-Avaya VSP  
-Brocade VDX  
-Brocade MLX/NetIron  
-Calix B6  
-Cisco WLC  
-Dell OS10  
-Dell-Force10  
-Dell PowerConnect  
-Huawei  
-Mellanox  
-NetApp cDOT  
-Palo Alto PAN-OS  
-Pluribus  
-Ruckus ICX/FastIron  
-Ubiquiti EdgeSwitch  
-Vyatta VyOS  
+- Alcatel AOS6/AOS8
+- Apresia Systems AEOS
+- Calix B6
+- Cisco WLC
+- Dell OS9 (Force10)
+- Dell OS10
+- Dell PowerConnect
+- Extreme ERS (Avaya)
+- Extreme VSP (Avaya)
+- Extreme VDX (Brocade)
+- Extreme MLX/NetIron (Brocade/Foundry)
+- Huawei
+- IP Infusion OcNOS
+- Mellanox
+- NetApp cDOT
+- Palo Alto PAN-OS
+- Pluribus
+- Ruckus ICX/FastIron
+- Ubiquiti EdgeSwitch
+- Vyatta VyOS
 
 ###### Experimental
 
-A10  
-Accedian  
-Aruba  
-Ciena SAOS  
-Citrix Netscaler  
-Cisco Telepresence  
-Check Point GAiA  
-Coriant  
-Dell EMC Isilon  
-Eltex  
-Enterasys  
-Extreme EXOS  
-Extreme Wing  
-F5 LTM  
-Fortinet  
-MRV Communications OptiSwitch  
-Nokia/Alcatel SR-OS  
-QuantaMesh  
+- A10
+- Accedian
+- Aruba
+- Ciena SAOS
+- Citrix Netscaler
+- Cisco Telepresence
+- Check Point GAiA
+- Coriant
+- Dell OS6
+- Dell EMC Isilon
+- Eltex
+- Enterasys
+- Extreme EXOS
+- Extreme Wing
+- Extreme SLX (Brocade)
+- F5 TMSH
+- F5 Linux
+- Fortinet
+- MRV Communications OptiSwitch
+- Nokia/Alcatel SR-OS
+- QuantaMesh
+- Rad ETX
 
 ## Tutorials:
 
@@ -131,12 +136,12 @@ print(output)
 ```
 ```
 Interface                  IP-Address      OK? Method Status                Protocol
-FastEthernet0              unassigned      YES unset  down                  down    
-FastEthernet1              unassigned      YES unset  down                  down    
-FastEthernet2              unassigned      YES unset  down                  down    
-FastEthernet3              unassigned      YES unset  down                  down    
-FastEthernet4              10.10.10.10     YES manual up                    up      
-Vlan1                      unassigned      YES unset  down                  down    
+FastEthernet0              unassigned      YES unset  down                  down
+FastEthernet1              unassigned      YES unset  down                  down
+FastEthernet2              unassigned      YES unset  down                  down
+FastEthernet3              unassigned      YES unset  down                  down
+FastEthernet4              10.10.10.10     YES manual up                    up
+Vlan1                      unassigned      YES unset  down                  down
 ```
 
 #### Execute configuration change commands (will automatically enter into config mode)
@@ -158,6 +163,16 @@ pynet-rtr1(config)#end
 pynet-rtr1#
 ```
 
+## TextFSM Integration
+
+Netmiko has been configured to automatically look in `~/ntc-template/templates/index` for the ntc-templates index file. Alternatively, you can explicitly tell Netmiko where to look for the TextFSM template directory by setting the `NET_TEXTFSM` environment variable (note, there must be an index file in this directory):
+
+```
+export NET_TEXTFSM=/path/to/ntc-templates/templates/
+```
+
+[More info on TextFSM and Netmiko](https://pynet.twb-tech.com/blog/automation/netmiko-textfsm.html).
+
 ## 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)
@@ -167,7 +182,7 @@ If you have questions or would like to discuss Netmiko, a Netmiko channel exists
 
 
 
----    
+---   
 Kirk Byers  
 Python for Network Engineers  
 https://pynet.twb-tech.com  
diff --git a/docs/build/html/classes/base_connection.html b/docs/build/html/classes/base_connection.html
index 4f2ff9a05..ed5a82338 100644
--- a/docs/build/html/classes/base_connection.html
+++ b/docs/build/html/classes/base_connection.html
@@ -434,7 +434,7 @@ <h1>BaseConnection<a class="headerlink" href="#baseconnection" title="Permalink
 ESC[E        Next line (HP does ESC-E)
 ESC[2K       Erase line
 ESC[1;24r    Enable scrolling from start to row end</p>
-<p>HP ProCurve&#8217;s, Cisco SG300, and F5 LTM&#8217;s require this (possible others)</p>
+<p>HP ProCurve&#8217;s, Cisco SG300, and F5 Big-IP&#8217;s require this (possible others)</p>
 </dd></dl>
 
 <dl class="staticmethod">
diff --git a/netmiko/__init__.py b/netmiko/__init__.py
index 8dcd39a0a..ec0c9a3d5 100644
--- a/netmiko/__init__.py
+++ b/netmiko/__init__.py
@@ -23,7 +23,7 @@
 NetmikoAuthError = NetMikoAuthenticationException
 Netmiko = ConnectHandler
 
-__version__ = '2.2.2'
+__version__ = '2.3.0'
 __all__ = ('ConnectHandler', 'ssh_dispatcher', 'platforms', 'SCPConn', 'FileTransfer',
            'NetMikoTimeoutException', 'NetMikoAuthenticationException',
            'NetmikoTimeoutError', 'NetmikoAuthError', 'InLineTransfer', 'redispatch',
diff --git a/netmiko/alcatel/alcatel_sros_ssh.py b/netmiko/alcatel/alcatel_sros_ssh.py
index 21ec9cf0b..192bb3b5b 100644
--- a/netmiko/alcatel/alcatel_sros_ssh.py
+++ b/netmiko/alcatel/alcatel_sros_ssh.py
@@ -25,7 +25,33 @@ def set_base_prompt(self, *args, **kwargs):
             self.base_prompt = match.group(1)
             return self.base_prompt
 
-    def enable(self, *args, **kwargs):
+    def enable(self, cmd='enable-admin', pattern='ssword', re_flags=re.IGNORECASE):
+        """Enter enable mode."""
+        return super(AlcatelSrosSSH, self).enable(cmd=cmd, pattern=pattern, re_flags=re_flags)
+
+    def check_enable_mode(self, check_string='CLI Already in admin mode'):
+        """Check whether we are in enable-admin mode.
+         SROS requires us to do this:
+        *A:HOSTNAME# enable-admin
+        MINOR: CLI Already in admin mode.
+        *A:HOSTNAME#
+        *A:HOSTNAME# enable-admin
+        Password:
+        MINOR: CLI Invalid password.
+        *A:HOSTNAME#
+        """
+        output = self.send_command_timing('enable-admin')
+        if re.search(r"ssword", output):
+            # Just hit enter as we don't actually want to enter enable here
+            self.write_channel(self.normalize_cmd(self.RETURN))
+            self.read_until_prompt()
+            return False
+        elif check_string in output:
+            return True
+        raise ValueError("Unexpected response in check_enable_mode() method")
+
+    def exit_enable_mode(self, exit_command=''):
+        """No corresponding exit of enable mode on SROS."""
         pass
 
     def config_mode(self, config_command='configure', pattern='#'):
diff --git a/netmiko/apresia/apresia_aeos.py b/netmiko/apresia/apresia_aeos.py
index e310218ad..2f1dfc900 100644
--- a/netmiko/apresia/apresia_aeos.py
+++ b/netmiko/apresia/apresia_aeos.py
@@ -19,7 +19,7 @@ def disable_paging(self, command="", delay_factor=1):
         check_command = "show running-config | include terminal length 0"
         output = self.send_command(check_command)
 
-        if "terminal length 0" not in output:
+        if self.allow_auto_change and "terminal length 0" not in output:
             self.send_config_set("terminal length 0")
         self.exit_enable_mode()
 
diff --git a/netmiko/aruba/aruba_ssh.py b/netmiko/aruba/aruba_ssh.py
index 98e929b29..b5ecf7f81 100644
--- a/netmiko/aruba/aruba_ssh.py
+++ b/netmiko/aruba/aruba_ssh.py
@@ -7,6 +7,11 @@
 
 class ArubaSSH(CiscoSSHConnection):
     """Aruba OS support"""
+    def __init__(self, **kwargs):
+        if kwargs.get('default_enter') is None:
+            kwargs['default_enter'] = '\r'
+        return super(ArubaSSH, self).__init__(**kwargs)
+
     def session_preparation(self):
         """Aruba OS requires enable mode to disable paging."""
         delay_factor = self.select_delay_factor(delay_factor=0)
diff --git a/netmiko/avaya/__init__.py b/netmiko/avaya/__init__.py
deleted file mode 100644
index 54bd407a9..000000000
--- a/netmiko/avaya/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import unicode_literals
-from netmiko.avaya.avaya_vsp_ssh import AvayaVspSSH
-from netmiko.avaya.avaya_ers_ssh import AvayaErsSSH
-
-__all__ = ['AvayaVspSSH', 'AvayaErsSSH']
diff --git a/netmiko/base_connection.py b/netmiko/base_connection.py
index 975e7ada3..c7e5a3334 100644
--- a/netmiko/base_connection.py
+++ b/netmiko/base_connection.py
@@ -23,7 +23,7 @@
 
 from netmiko import log
 from netmiko.netmiko_globals import MAX_BUFFER, BACKSPACE_CHAR
-from netmiko.py23_compat import string_types, bufferedio_types
+from netmiko.py23_compat import string_types, bufferedio_types, text_type
 from netmiko.ssh_exception import NetMikoTimeoutException, NetMikoAuthenticationException
 from netmiko.utilities import write_bytes, check_serial_port, get_structured_data
 
@@ -36,11 +36,13 @@ class BaseConnection(object):
     """
     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,
+                 key_file=None, pkey=None, passphrase=None, allow_agent=False,
+                 ssh_strict=False, system_host_keys=False,
                  alt_host_keys=False, alt_key_file='', ssh_config_file=None, timeout=100,
-                 session_timeout=60, blocking_timeout=8, keepalive=0, default_enter=None,
-                 response_return=None, serial_settings=None, fast_cli=False, session_log=None,
-                 session_log_record_writes=False, session_log_file_mode='write'):
+                 session_timeout=60, auth_timeout=None, blocking_timeout=8, keepalive=0,
+                 default_enter=None, response_return=None, serial_settings=None, fast_cli=False,
+                 session_log=None, session_log_record_writes=False, session_log_file_mode='write',
+                 allow_auto_change=False, encoding='ascii'):
         """
         Initialize attributes for establishing connection to target device.
 
@@ -82,6 +84,13 @@ def __init__(self, ip='', host='', username='', password='', secret='', port=Non
         :param key_file: Filename path of the SSH key file to use.
         :type key_file: str
 
+        :param pkey: SSH key object to use.
+        :type pkey: paramiko.PKey
+
+        :param passphrase: Passphrase to use for encrypted key; password will be used for key
+                decryption if not specified.
+        :type passphrase: str
+
         :param allow_agent: Enable use of SSH key-agent.
         :type allow_agent: bool
 
@@ -107,6 +116,9 @@ def __init__(self, ip='', host='', username='', password='', secret='', port=Non
         :param session_timeout: Set a timeout for parallel requests.
         :type session_timeout: float
 
+        :param auth_timeout: Set a timeout (in seconds) to wait for an authentication response.
+        :type auth_timeout: float
+
         :param keepalive: Send SSH keepalive packets at a specific interval, in seconds.
                 Currently defaults to 0, for backwards compatibility (it will not attempt
                 to keep the connection alive).
@@ -135,6 +147,14 @@ def __init__(self, ip='', host='', username='', password='', secret='', port=Non
         :param session_log_file_mode: "write" or "append" for session_log file mode
                 (default: "write")
         :type session_log_file_mode: str
+
+        :param allow_auto_change: Allow automatic configuration changes for terminal settings.
+                (default: False)
+        :type allow_auto_change: bool
+
+        :param encoding: Encoding to be used when writing bytes to the output channel.
+                (default: 'ascii')
+        :type encoding: str
         """
         self.remote_conn = None
         self.RETURN = '\n' if default_enter is None else default_enter
@@ -162,9 +182,12 @@ def __init__(self, ip='', host='', username='', password='', secret='', port=Non
         self.ansi_escape_codes = False
         self.verbose = verbose
         self.timeout = timeout
+        self.auth_timeout = auth_timeout
         self.session_timeout = session_timeout
         self.blocking_timeout = blocking_timeout
         self.keepalive = keepalive
+        self.allow_auto_change = allow_auto_change
+        self.encoding = encoding
 
         # Netmiko will close the session_log if we open the file
         self.session_log = None
@@ -216,12 +239,12 @@ def __init__(self, ip='', host='', username='', password='', secret='', port=Non
             self.protocol = 'telnet'
             self._modify_connection_params()
             self.establish_connection()
-            self.session_preparation()
+            self._try_session_preparation()
         elif '_serial' in device_type:
             self.protocol = 'serial'
             self._modify_connection_params()
             self.establish_connection()
-            self.session_preparation()
+            self._try_session_preparation()
         else:
             self.protocol = 'ssh'
 
@@ -233,6 +256,8 @@ def __init__(self, ip='', host='', username='', password='', secret='', port=Non
             # Options for SSH host_keys
             self.use_keys = use_keys
             self.key_file = key_file
+            self.pkey = pkey
+            self.passphrase = passphrase
             self.allow_agent = allow_agent
             self.system_host_keys = system_host_keys
             self.alt_host_keys = alt_host_keys
@@ -243,7 +268,7 @@ def __init__(self, ip='', host='', username='', password='', secret='', port=Non
 
             self._modify_connection_params()
             self.establish_connection()
-            self.session_preparation()
+            self._try_session_preparation()
 
     def __enter__(self):
         """Establish a session using a Context Manager."""
@@ -303,16 +328,16 @@ def _write_channel(self, out_data):
         :type out_data: str (can be either unicode/byte string)
         """
         if self.protocol == 'ssh':
-            self.remote_conn.sendall(write_bytes(out_data))
+            self.remote_conn.sendall(write_bytes(out_data, encoding=self.encoding))
         elif self.protocol == 'telnet':
-            self.remote_conn.write(write_bytes(out_data))
+            self.remote_conn.write(write_bytes(out_data, encoding=self.encoding))
         elif self.protocol == 'serial':
-            self.remote_conn.write(write_bytes(out_data))
+            self.remote_conn.write(write_bytes(out_data, encoding=self.encoding))
             self.remote_conn.flush()
         else:
             raise ValueError("Invalid protocol specified")
         try:
-            log.debug("write_channel: {}".format(write_bytes(out_data)))
+            log.debug("write_channel: {}".format(write_bytes(out_data, encoding=self.encoding)))
             if self._session_log_fin or self.session_log_record_writes:
                 self._write_session_log(out_data)
         except UnicodeDecodeError:
@@ -321,7 +346,7 @@ def _write_channel(self, out_data):
 
     def _write_session_log(self, data):
         if self.session_log is not None and len(data) > 0:
-            self.session_log.write(write_bytes(data))
+            self.session_log.write(write_bytes(data, encoding=self.encoding))
             self.session_log.flush()
 
     def write_channel(self, out_data):
@@ -345,10 +370,13 @@ def is_alive(self):
             return False
         if self.protocol == 'telnet':
             try:
-                # Try sending IAC + NOP (IAC is telnet way of sending command
-                # IAC = Interpret as Command (it comes before the NOP)
+                # Try sending IAC + NOP (IAC is telnet way of sending command)
+                # IAC = Interpret as Command; it comes before the NOP.
                 log.debug("Sending IAC + NOP")
-                self.write_channel(telnetlib.IAC + telnetlib.NOP)
+                # Need to send multiple times to test connection
+                self.remote_conn.sock.sendall(telnetlib.IAC + telnetlib.NOP)
+                self.remote_conn.sock.sendall(telnetlib.IAC + telnetlib.NOP)
+                self.remote_conn.sock.sendall(telnetlib.IAC + telnetlib.NOP)
                 return True
             except AttributeError:
                 return False
@@ -611,6 +639,19 @@ def telnet_login(self, pri_prompt_terminator=r'#\s*$', alt_prompt_terminator=r'>
         self.remote_conn.close()
         raise NetMikoAuthenticationException(msg)
 
+    def _try_session_preparation(self):
+        """
+        In case of an exception happening during `session_preparation()` Netmiko should
+        gracefully clean-up after itself. This might be challenging for library users
+        to do since they don't have a reference to the object. This is possibly related
+        to threads used in Paramiko.
+        """
+        try:
+            self.session_preparation()
+        except Exception:
+            self.disconnect()
+            raise
+
     def session_preparation(self):
         """
         Prepare the session after the connection has been established
@@ -681,7 +722,10 @@ def _connect_params_dict(self):
             'look_for_keys': self.use_keys,
             'allow_agent': self.allow_agent,
             'key_filename': self.key_file,
+            'pkey': self.pkey,
+            'passphrase': self.passphrase,
             'timeout': self.timeout,
+            'auth_timeout': self.auth_timeout
         }
 
         # Check if using SSH 'config' file mainly for SSH proxy support
@@ -745,7 +789,7 @@ def establish_connection(self, width=None, height=None):
                 self.paramiko_cleanup()
                 msg = "Authentication failure: unable to connect {device_type} {ip}:{port}".format(
                     device_type=self.device_type, ip=self.host, port=self.port)
-                msg += self.RETURN + str(auth_err)
+                msg += self.RETURN + text_type(auth_err)
                 raise NetMikoAuthenticationException(msg)
 
             if self.verbose:
@@ -841,7 +885,7 @@ def select_delay_factor(self, delay_factor):
                 return self.global_delay_factor
 
     def special_login_handler(self, delay_factor=1):
-        """Handler for devices like WLC, Avaya ERS that throw up characters prior to login."""
+        """Handler for devices like WLC, Extreme ERS that throw up characters prior to login."""
         pass
 
     def disable_paging(self, command="terminal length 0", delay_factor=1):
@@ -1016,6 +1060,33 @@ def strip_prompt(self, a_string):
         else:
             return a_string
 
+    def _first_line_handler(self, data, search_pattern):
+        """
+        In certain situations the first line will get repainted which causes a false
+        match on the terminating pattern.
+
+        Filter this out.
+
+        returns a tuple of (data, first_line_processed)
+
+        Where data is the original data potentially with the first line modified
+        and the first_line_processed is a flag indicating that we have handled the
+        first line.
+        """
+        try:
+            # First line is the echo line containing the command. In certain situations
+            # it gets repainted and needs filtered
+            lines = data.split(self.RETURN)
+            first_line = lines[0]
+            if BACKSPACE_CHAR in first_line:
+                pattern = search_pattern + r'.*$'
+                first_line = re.sub(pattern, repl='', string=first_line)
+                lines[0] = first_line
+                data = self.RETURN.join(lines)
+            return (data, True)
+        except IndexError:
+            return (data, False)
+
     def send_command(self, command_string, expect_string=None,
                      delay_factor=1, max_loops=500, auto_find_prompt=True,
                      strip_prompt=True, strip_command=True, normalize=True,
@@ -1083,27 +1154,32 @@ def send_command(self, command_string, expect_string=None,
 
         i = 1
         output = ''
+        first_line_processed = False
+
         # Keep reading data until search_pattern is found or until max_loops is reached.
         while i <= max_loops:
             new_data = self.read_channel()
             if new_data:
                 if self.ansi_escape_codes:
                     new_data = self.strip_ansi_escape_codes(new_data)
-                output += new_data
-                try:
-                    lines = output.split(self.RETURN)
-                    first_line = lines[0]
-                    # First line is the echo line containing the command. In certain situations
-                    # it gets repainted and needs filtered
-                    if BACKSPACE_CHAR in first_line:
-                        pattern = search_pattern + r'.*$'
-                        first_line = re.sub(pattern, repl='', string=first_line)
-                        lines[0] = first_line
-                        output = self.RETURN.join(lines)
-                except IndexError:
-                    pass
-                if re.search(search_pattern, output):
-                    break
+
+                # Case where we haven't processed the first_line yet (there is a potential issue
+                # in the first line (in cases where the line is repainted).
+                if not first_line_processed:
+                    output += new_data
+                    output, first_line_processed = self._first_line_handler(
+                        output,
+                        search_pattern
+                    )
+                    # Check if we have already found our pattern
+                    if re.search(search_pattern, output):
+                        break
+
+                else:
+                    output += new_data
+                    # Check if pattern is in the incremental data
+                    if re.search(search_pattern, new_data):
+                        break
 
             time.sleep(delay_factor * loop_delay)
             i += 1
@@ -1391,7 +1467,7 @@ def strip_ansi_escape_codes(self, string_buffer):
                      ESC[\d\d;\d\dm and ESC[\d\d;\d\d;\d\dm
         ESC[6n       Get cursor position
 
-        HP ProCurve's, Cisco SG300, and F5 LTM's require this (possible others)
+        HP ProCurve and Cisco SG300 require this (possible others).
 
         :param string_buffer: The string to be processed to remove ANSI escape codes
         :type string_buffer: str
diff --git a/netmiko/brocade/__init__.py b/netmiko/brocade/__init__.py
deleted file mode 100644
index 6b3eb01ec..000000000
--- a/netmiko/brocade/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-from netmiko.brocade.brocade_nos_ssh import BrocadeNosSSH
-from netmiko.brocade.brocade_netiron import BrocadeNetironSSH
-from netmiko.brocade.brocade_netiron import BrocadeNetironTelnet
-
-__all__ = ['BrocadeNosSSH', 'BrocadeNetironSSH', 'BrocadeNetironTelnet']
diff --git a/netmiko/cisco/cisco_asa_ssh.py b/netmiko/cisco/cisco_asa_ssh.py
index ce46bf6c2..6067a76ff 100644
--- a/netmiko/cisco/cisco_asa_ssh.py
+++ b/netmiko/cisco/cisco_asa_ssh.py
@@ -17,7 +17,13 @@ def session_preparation(self):
         else:
             self.asa_login()
         self.disable_paging(command="terminal pager 0")
-        self.set_terminal_width(command="terminal width 511")
+        if self.allow_auto_change:
+            try:
+                self.send_config_set("terminal width 511")
+            except ValueError:
+                # Don't fail for the terminal width
+                pass
+
         # Clear the read buffer
         time.sleep(.3 * self.global_delay_factor)
         self.clear_buffer()
diff --git a/netmiko/cisco/cisco_xr_ssh.py b/netmiko/cisco/cisco_xr_ssh.py
index 7ada09150..12c79ce33 100644
--- a/netmiko/cisco/cisco_xr_ssh.py
+++ b/netmiko/cisco/cisco_xr_ssh.py
@@ -3,6 +3,7 @@
 import time
 import re
 from netmiko.cisco_base_connection import CiscoSSHConnection, CiscoFileTransfer
+from netmiko.py23_compat import text_type
 
 
 class CiscoXrSSH(CiscoSSHConnection):
@@ -70,22 +71,23 @@ def commit(self, confirm=False, confirm_delay=None, comment='', label='', delay_
                 raise ValueError("Invalid comment contains double quote")
             comment = '"{0}"'.format(comment)
 
-        label = str(label)
+        label = text_type(label)
         error_marker = 'Failed to'
         alt_error_marker = 'One or more commits have occurred from other'
 
         # Select proper command string based on arguments provided
         if label:
             if comment:
-                command_string = 'commit label {0} comment {1}'.format(label, comment)
+                command_string = 'commit label {} comment {}'.format(label, comment)
             elif confirm:
-                command_string = 'commit label {0} confirmed {1}'.format(label, str(confirm_delay))
+                command_string = 'commit label {} confirmed {}'.format(label,
+                                                                       text_type(confirm_delay))
             else:
-                command_string = 'commit label {0}'.format(label)
+                command_string = 'commit label {}'.format(label)
         elif confirm:
-            command_string = 'commit confirmed {0}'.format(str(confirm_delay))
+            command_string = 'commit confirmed {}'.format(text_type(confirm_delay))
         elif comment:
-            command_string = 'commit comment {0}'.format(comment)
+            command_string = 'commit comment {}'.format(comment)
         else:
             command_string = 'commit'
 
@@ -99,7 +101,7 @@ def commit(self, confirm=False, confirm_delay=None, comment='', label='', delay_
             # Other commits occurred, don't proceed with commit
             output += self.send_command_timing("no", strip_prompt=False, strip_command=False,
                                                delay_factor=delay_factor)
-            raise ValueError("Commit failed with the following errors:\n\n{0}".format(output))
+            raise ValueError("Commit failed with the following errors:\n\n{}".format(output))
 
         return output
 
diff --git a/netmiko/dell/__init__.py b/netmiko/dell/__init__.py
index c2958189c..308a5d76d 100644
--- a/netmiko/dell/__init__.py
+++ b/netmiko/dell/__init__.py
@@ -1,4 +1,6 @@
 from __future__ import unicode_literals
+from netmiko.dell.dell_dnos6 import DellDNOS6SSH
+from netmiko.dell.dell_dnos6 import DellDNOS6Telnet
 from netmiko.dell.dell_force10_ssh import DellForce10SSH
 from netmiko.dell.dell_os10_ssh import DellOS10SSH, DellOS10FileTransfer
 from netmiko.dell.dell_powerconnect import DellPowerConnectSSH
@@ -6,4 +8,5 @@
 from netmiko.dell.dell_isilon_ssh import DellIsilonSSH
 
 __all__ = ['DellForce10SSH', 'DellPowerConnectSSH', 'DellPowerConnectTelnet',
-           'DellOS10SSH', 'DellOS10FileTransfer', 'DellIsilonSSH']
+           'DellOS10SSH', 'DellOS10FileTransfer', 'DellIsilonSSH',
+           'DellDNOS6SSH', 'DellDNOS6Telnet']
diff --git a/netmiko/dell/dell_dnos6.py b/netmiko/dell/dell_dnos6.py
new file mode 100644
index 000000000..7bf3d3465
--- /dev/null
+++ b/netmiko/dell/dell_dnos6.py
@@ -0,0 +1,30 @@
+"""Dell N2/3/4000 base driver- supports DNOS6."""
+from __future__ import unicode_literals
+from netmiko.dell.dell_powerconnect import DellPowerConnectBase
+import time
+
+
+class DellDNOS6Base(DellPowerConnectBase):
+    def session_preparation(self):
+        """Prepare the session after the connection has been established."""
+        self.ansi_escape_codes = True
+        self._test_channel_read()
+        self.set_base_prompt()
+        self.enable()
+        self.disable_paging(command="terminal length 0")
+        self.set_terminal_width()
+        # Clear the read buffer
+        time.sleep(.3 * self.global_delay_factor)
+        self.clear_buffer()
+
+    def save_config(self, cmd='copy running-configuration startup-configuration', confirm=False):
+        """Saves Config"""
+        return super(DellDNOS6SSH, self).save_config(cmd=cmd, confirm=confirm)
+
+
+class DellDNOS6SSH(DellDNOS6Base):
+    pass
+
+
+class DellDNOS6Telnet(DellDNOS6Base):
+    pass
diff --git a/netmiko/extreme/__init__.py b/netmiko/extreme/__init__.py
index 1074d9428..5cf4877f1 100644
--- a/netmiko/extreme/__init__.py
+++ b/netmiko/extreme/__init__.py
@@ -1,6 +1,14 @@
 from __future__ import unicode_literals
-from netmiko.extreme.extreme_exos import ExtremeSSH
-from netmiko.extreme.extreme_exos import ExtremeTelnet
+from netmiko.extreme.extreme_ers_ssh import ExtremeErsSSH
+from netmiko.extreme.extreme_exos import ExtremeExosSSH
+from netmiko.extreme.extreme_exos import ExtremeExosTelnet
+from netmiko.extreme.extreme_netiron import ExtremeNetironSSH
+from netmiko.extreme.extreme_netiron import ExtremeNetironTelnet
+from netmiko.extreme.extreme_nos_ssh import ExtremeNosSSH
+from netmiko.extreme.extreme_slx_ssh import ExtremeSlxSSH
+from netmiko.extreme.extreme_vsp_ssh import ExtremeVspSSH
 from netmiko.extreme.extreme_wing_ssh import ExtremeWingSSH
 
-__all__ = ['ExtremeSSH', 'ExtremeWingSSH', 'ExtremeTelnet']
+__all__ = ['ExtremeErsSSH', 'ExtremeExosSSH', 'ExtremeExosTelnet',
+           'ExtremeNetironSSH', 'ExtremeNetironTelnet', 'ExtremeNosSSH',
+           'ExtremeSlxSSH', 'ExtremeVspSSH', 'ExtremeWingSSH']
diff --git a/netmiko/avaya/avaya_ers_ssh.py b/netmiko/extreme/extreme_ers_ssh.py
similarity index 75%
rename from netmiko/avaya/avaya_ers_ssh.py
rename to netmiko/extreme/extreme_ers_ssh.py
index f234b78dc..e51848405 100644
--- a/netmiko/avaya/avaya_ers_ssh.py
+++ b/netmiko/extreme/extreme_ers_ssh.py
@@ -1,18 +1,18 @@
-"""Netmiko support for Avaya Ethernet Routing Switch."""
+"""Netmiko support for Extreme Ethernet Routing Switch."""
 from __future__ import print_function
 from __future__ import unicode_literals
 import time
 from netmiko.cisco_base_connection import CiscoSSHConnection
 
-# Avaya presents Enter Ctrl-Y to begin.
+# Extreme ERS presents Enter Ctrl-Y to begin.
 CTRL_Y = '\x19'
 
 
-class AvayaErsSSH(CiscoSSHConnection):
-    """Netmiko support for Avaya Ethernet Routing Switch."""
+class ExtremeErsSSH(CiscoSSHConnection):
+    """Netmiko support for Extreme Ethernet Routing Switch."""
     def special_login_handler(self, delay_factor=1):
         """
-        Avaya ERS presents the following as part of the login process:
+        Extreme ERS presents the following as part of the login process:
 
         Enter Ctrl-Y to begin.
         """
@@ -39,4 +39,4 @@ def special_login_handler(self, delay_factor=1):
 
     def save_config(self, cmd='save config', confirm=False):
         """Save Config"""
-        return super(AvayaErsSSH, self).save_config(cmd=cmd, confirm=confirm)
+        return super(ExtremeErsSSH, self).save_config(cmd=cmd, confirm=confirm)
diff --git a/netmiko/extreme/extreme_exos.py b/netmiko/extreme/extreme_exos.py
index 94e406a81..a116c82ac 100644
--- a/netmiko/extreme/extreme_exos.py
+++ b/netmiko/extreme/extreme_exos.py
@@ -5,8 +5,8 @@
 from netmiko.cisco_base_connection import CiscoSSHConnection
 
 
-class ExtremeBase(CiscoSSHConnection):
-    """Extreme support.
+class ExtremeExosBase(CiscoSSHConnection):
+    """Extreme Exos support.
 
     Designed for EXOS >= 15.0
     """
@@ -34,7 +34,7 @@ def set_base_prompt(self, *args, **kwargs):
             * testhost.4 #
             * testhost.5 #
         """
-        cur_base_prompt = super(ExtremeBase, self).set_base_prompt(*args, **kwargs)
+        cur_base_prompt = super(ExtremeExosBase, self).set_base_prompt(*args, **kwargs)
         # Strip off any leading * or whitespace chars; strip off trailing period and digits
         match = re.search(r'[\*\s]*(.*)\.\d+', cur_base_prompt)
         if match:
@@ -51,31 +51,31 @@ def send_command(self, *args, **kwargs):
 
         # refresh self.base_prompt
         self.set_base_prompt()
-        return super(ExtremeBase, self).send_command(*args, **kwargs)
+        return super(ExtremeExosBase, self).send_command(*args, **kwargs)
 
     def config_mode(self, config_command=''):
-        """No configuration mode on Extreme."""
+        """No configuration mode on Extreme Exos."""
         return ''
 
     def check_config_mode(self, check_string='#'):
         """Checks whether in configuration mode. Returns a boolean."""
-        return super(ExtremeBase, self).check_config_mode(check_string=check_string)
+        return super(ExtremeExosBase, self).check_config_mode(check_string=check_string)
 
     def exit_config_mode(self, exit_config=''):
-        """No configuration mode on Extreme."""
+        """No configuration mode on Extreme Exos."""
         return ''
 
     def save_config(self, cmd='save configuration primary', confirm=False):
         """Saves configuration."""
-        return super(ExtremeBase, self).save_config(cmd=cmd, confirm=confirm)
+        return super(ExtremeExosBase, self).save_config(cmd=cmd, confirm=confirm)
 
 
-class ExtremeSSH(ExtremeBase):
+class ExtremeExosSSH(ExtremeExosBase):
     pass
 
 
-class ExtremeTelnet(ExtremeBase):
+class ExtremeExosTelnet(ExtremeExosBase):
     def __init__(self, *args, **kwargs):
         default_enter = kwargs.get('default_enter')
         kwargs['default_enter'] = '\r\n' if default_enter is None else default_enter
-        super(ExtremeTelnet, self).__init__(*args, **kwargs)
+        super(ExtremeExosTelnet, self).__init__(*args, **kwargs)
diff --git a/netmiko/brocade/brocade_netiron.py b/netmiko/extreme/extreme_netiron.py
similarity index 60%
rename from netmiko/brocade/brocade_netiron.py
rename to netmiko/extreme/extreme_netiron.py
index 153879cdb..39ad3861b 100644
--- a/netmiko/brocade/brocade_netiron.py
+++ b/netmiko/extreme/extreme_netiron.py
@@ -2,18 +2,18 @@
 from netmiko.cisco_base_connection import CiscoSSHConnection
 
 
-class BrocadeNetironBase(CiscoSSHConnection):
+class ExtremeNetironBase(CiscoSSHConnection):
     def save_config(self, cmd='write memory', confirm=False):
         """Save Config"""
-        return super(BrocadeNetironBase, self).save_config(cmd=cmd, confirm=confirm)
+        return super(ExtremeNetironBase, self).save_config(cmd=cmd, confirm=confirm)
 
 
-class BrocadeNetironSSH(BrocadeNetironBase):
+class ExtremeNetironSSH(ExtremeNetironBase):
     pass
 
 
-class BrocadeNetironTelnet(BrocadeNetironBase):
+class ExtremeNetironTelnet(ExtremeNetironBase):
     def __init__(self, *args, **kwargs):
         default_enter = kwargs.get('default_enter')
         kwargs['default_enter'] = '\r\n' if default_enter is None else default_enter
-        super(BrocadeNetironTelnet, self).__init__(*args, **kwargs)
+        super(ExtremeNetironTelnet, self).__init__(*args, **kwargs)
diff --git a/netmiko/brocade/brocade_nos_ssh.py b/netmiko/extreme/extreme_nos_ssh.py
similarity index 69%
rename from netmiko/brocade/brocade_nos_ssh.py
rename to netmiko/extreme/extreme_nos_ssh.py
index 4eb315b31..49135fec1 100644
--- a/netmiko/brocade/brocade_nos_ssh.py
+++ b/netmiko/extreme/extreme_nos_ssh.py
@@ -1,17 +1,17 @@
-"""Support for Brocade NOS/VDX."""
+"""Support for Extreme NOS/VDX."""
 from __future__ import unicode_literals
 import time
 from netmiko.cisco_base_connection import CiscoSSHConnection
 
 
-class BrocadeNosSSH(CiscoSSHConnection):
-    """Support for Brocade NOS/VDX."""
+class ExtremeNosSSH(CiscoSSHConnection):
+    """Support for Extreme NOS/VDX."""
     def enable(self, *args, **kwargs):
-        """No enable mode on Brocade VDX."""
+        """No enable mode on Extreme VDX."""
         pass
 
     def exit_enable_mode(self, *args, **kwargs):
-        """No enable mode on Brocade VDX."""
+        """No enable mode on Extreme VDX."""
         pass
 
     def special_login_handler(self, delay_factor=1):
@@ -22,6 +22,6 @@ def special_login_handler(self, delay_factor=1):
 
     def save_config(self, cmd='copy running-config startup-config', confirm=True,
                     confirm_response='y'):
-        """Save Config for Brocade VDX."""
-        return super(BrocadeNosSSH, self).save_config(cmd=cmd, confirm=confirm,
+        """Save Config for Extreme VDX."""
+        return super(ExtremeNosSSH, self).save_config(cmd=cmd, confirm=confirm,
                                                       confirm_response=confirm_response)
diff --git a/netmiko/extreme/extreme_slx_ssh.py b/netmiko/extreme/extreme_slx_ssh.py
new file mode 100644
index 000000000..74aa91495
--- /dev/null
+++ b/netmiko/extreme/extreme_slx_ssh.py
@@ -0,0 +1,28 @@
+"""Support for Extreme SLX."""
+from __future__ import unicode_literals
+import time
+from netmiko.cisco_base_connection import CiscoSSHConnection
+
+
+class ExtremeSlxSSH(CiscoSSHConnection):
+    """Support for Extreme SLX."""
+    def enable(self, *args, **kwargs):
+        """No enable mode on Extreme SLX."""
+        pass
+
+    def exit_enable_mode(self, *args, **kwargs):
+        """No enable mode on Extreme Slx."""
+        pass
+
+    def special_login_handler(self, delay_factor=1):
+        """Adding a delay after login."""
+        delay_factor = self.select_delay_factor(delay_factor)
+        self.write_channel(self.RETURN)
+        time.sleep(1 * delay_factor)
+
+    def save_config(self, cmd='copy running-config startup-config',
+                    confirm=True, confirm_response='y'):
+        """Save Config for Extreme SLX."""
+        return super(ExtremeSlxSSH, self).save_config(cmd=cmd,
+                                                      confirm=confirm,
+                                                      confirm_response=confirm_response)
diff --git a/netmiko/avaya/avaya_vsp_ssh.py b/netmiko/extreme/extreme_vsp_ssh.py
similarity index 72%
rename from netmiko/avaya/avaya_vsp_ssh.py
rename to netmiko/extreme/extreme_vsp_ssh.py
index a5cade6c2..daf8e0967 100644
--- a/netmiko/avaya/avaya_vsp_ssh.py
+++ b/netmiko/extreme/extreme_vsp_ssh.py
@@ -1,12 +1,12 @@
-"""Avaya Virtual Services Platform Support."""
+"""Extreme Virtual Services Platform Support."""
 from __future__ import print_function
 from __future__ import unicode_literals
 import time
 from netmiko.cisco_base_connection import CiscoSSHConnection
 
 
-class AvayaVspSSH(CiscoSSHConnection):
-    """Avaya Virtual Services Platform Support."""
+class ExtremeVspSSH(CiscoSSHConnection):
+    """Extreme Virtual Services Platform Support."""
     def session_preparation(self):
         """Prepare the session after the connection has been established."""
         self._test_channel_read()
@@ -18,4 +18,4 @@ def session_preparation(self):
 
     def save_config(self, cmd='save config', confirm=False):
         """Save Config"""
-        return super(AvayaVspSSH, self).save_config(cmd=cmd, confirm=confirm)
+        return super(ExtremeVspSSH, self).save_config(cmd=cmd, confirm=confirm)
diff --git a/netmiko/f5/__init__.py b/netmiko/f5/__init__.py
index a6c60f8cc..6189a1ee5 100644
--- a/netmiko/f5/__init__.py
+++ b/netmiko/f5/__init__.py
@@ -1,4 +1,5 @@
 from __future__ import unicode_literals
-from netmiko.f5.f5_ltm_ssh import F5LtmSSH
+from netmiko.f5.f5_tmsh_ssh import F5TmshSSH
+from netmiko.f5.f5_linux_ssh import F5LinuxSSH
 
-__all__ = ['F5LtmSSH']
+__all__ = ['F5TmshSSH', 'F5LinuxSSH']
diff --git a/netmiko/f5/f5_linux_ssh.py b/netmiko/f5/f5_linux_ssh.py
new file mode 100644
index 000000000..3f31c38a5
--- /dev/null
+++ b/netmiko/f5/f5_linux_ssh.py
@@ -0,0 +1,6 @@
+from __future__ import unicode_literals
+from netmiko.linux.linux_ssh import LinuxSSH
+
+
+class F5LinuxSSH(LinuxSSH):
+    pass
diff --git a/netmiko/f5/f5_ltm_ssh.py b/netmiko/f5/f5_tmsh_ssh.py
similarity index 96%
rename from netmiko/f5/f5_ltm_ssh.py
rename to netmiko/f5/f5_tmsh_ssh.py
index 0b7c84a29..a439c9791 100644
--- a/netmiko/f5/f5_ltm_ssh.py
+++ b/netmiko/f5/f5_tmsh_ssh.py
@@ -3,7 +3,7 @@
 from netmiko.base_connection import BaseConnection
 
 
-class F5LtmSSH(BaseConnection):
+class F5TmshSSH(BaseConnection):
 
     def session_preparation(self):
         """Prepare the session after the connection has been established."""
diff --git a/netmiko/huawei/huawei_ssh.py b/netmiko/huawei/huawei_ssh.py
index 2c584a762..a42feb0ce 100644
--- a/netmiko/huawei/huawei_ssh.py
+++ b/netmiko/huawei/huawei_ssh.py
@@ -21,9 +21,10 @@ def config_mode(self, config_command='system-view'):
         """Enter configuration mode."""
         return super(HuaweiSSH, self).config_mode(config_command=config_command)
 
-    def exit_config_mode(self, exit_config='return'):
+    def exit_config_mode(self, exit_config='return', pattern=r'>'):
         """Exit configuration mode."""
-        return super(HuaweiSSH, self).exit_config_mode(exit_config=exit_config)
+        return super(HuaweiSSH, self).exit_config_mode(exit_config=exit_config,
+                                                       pattern=pattern)
 
     def check_config_mode(self, check_string=']'):
         """Checks whether in configuration mode. Returns a boolean."""
diff --git a/netmiko/ipinfusion/__init__.py b/netmiko/ipinfusion/__init__.py
new file mode 100644
index 000000000..66158c272
--- /dev/null
+++ b/netmiko/ipinfusion/__init__.py
@@ -0,0 +1,4 @@
+from __future__ import unicode_literals
+from netmiko.ipinfusion.ipinfusion_ocnos import IpInfusionOcNOSSSH, IpInfusionOcNOSTelnet
+
+__all__ = ['IpInfusionOcNOSSSH', 'IpInfusionOcNOSTelnet']
diff --git a/netmiko/ipinfusion/ipinfusion_ocnos.py b/netmiko/ipinfusion/ipinfusion_ocnos.py
new file mode 100644
index 000000000..ad3d44990
--- /dev/null
+++ b/netmiko/ipinfusion/ipinfusion_ocnos.py
@@ -0,0 +1,60 @@
+from __future__ import unicode_literals
+import time
+from telnetlib import IAC, DO, DONT, WILL, WONT, SB, SE, TTYPE
+from netmiko.cisco_base_connection import CiscoBaseConnection
+
+
+class IpInfusionOcNOSBase(CiscoBaseConnection):
+    """Common Methods for IP Infusion OcNOS support."""
+    def __init__(self, *args, **kwargs):
+        if kwargs.get('default_enter') is None:
+            kwargs['default_enter'] = '\r'
+        return super(IpInfusionOcNOSBase, self).__init__(**kwargs)
+
+    def session_preparation(self):
+        self._test_channel_read()
+        self.set_base_prompt()
+        self.disable_paging(command="terminal length 0")
+
+        # Clear the read buffer
+        time.sleep(.3 * self.global_delay_factor)
+        self.clear_buffer()
+
+    def save_config(self, cmd='write', confirm=False, confirm_response=''):
+        """Saves Config Using write command"""
+        return super(IpInfusionOcNOSBase, self).save_config(
+            cmd=cmd, confirm=confirm, confirm_response=confirm_response)
+
+
+class IpInfusionOcNOSSSH(IpInfusionOcNOSBase):
+    """IP Infusion OcNOS SSH driver."""
+    pass
+
+
+class IpInfusionOcNOSTelnet(IpInfusionOcNOSBase):
+    """IP Infusion OcNOS  Telnet driver."""
+
+    def _process_option(self, tsocket, command, option):
+        """
+        For all telnet options, re-implement the default telnetlib behaviour
+        and refuse to handle any options. If the server expresses interest in
+        'terminal type' option, then reply back with 'xterm' terminal type.
+        """
+        if command == DO and option == TTYPE:
+            tsocket.sendall(IAC + WILL + TTYPE)
+            tsocket.sendall(IAC + SB + TTYPE + b'\0' + b'xterm' + IAC + SE)
+        elif command in (DO, DONT):
+            tsocket.sendall(IAC + WONT + option)
+        elif command in (WILL, WONT):
+            tsocket.sendall(IAC + DONT + option)
+
+    def telnet_login(self, pri_prompt_terminator='#', alt_prompt_terminator='>',
+                     username_pattern=r"(?:user:|sername|login|user name)", pwd_pattern=r"assword:",
+                     delay_factor=1, max_loops=20):
+        # set callback function to handle telnet options.
+        self.remote_conn.set_option_negotiation_callback(self._process_option)
+        return super(IpInfusionOcNOSTelnet, self).telnet_login(
+            pri_prompt_terminator=pri_prompt_terminator,
+            alt_prompt_terminator=alt_prompt_terminator,
+            username_pattern=username_pattern, pwd_pattern=pwd_pattern,
+            delay_factor=delay_factor, max_loops=max_loops)
diff --git a/netmiko/juniper/juniper.py b/netmiko/juniper/juniper.py
index 269b745d2..e40a41bf7 100644
--- a/netmiko/juniper/juniper.py
+++ b/netmiko/juniper/juniper.py
@@ -5,6 +5,7 @@
 
 from netmiko.base_connection import BaseConnection
 from netmiko.scp_handler import BaseFileTransfer
+from netmiko.py23_compat import text_type
 
 
 class JuniperBase(BaseConnection):
@@ -127,7 +128,7 @@ def commit(self, confirm=False, confirm_delay=None, check=False, comment='',
             commit_marker = 'configuration check succeeds'
         elif confirm:
             if confirm_delay:
-                command_string = 'commit confirmed ' + str(confirm_delay)
+                command_string = 'commit confirmed ' + text_type(confirm_delay)
             else:
                 command_string = 'commit confirmed'
             commit_marker = 'commit confirmed will be automatically rolled back in'
diff --git a/netmiko/mrv/mrv_ssh.py b/netmiko/mrv/mrv_ssh.py
index dddbe7412..14bee22df 100644
--- a/netmiko/mrv/mrv_ssh.py
+++ b/netmiko/mrv/mrv_ssh.py
@@ -11,11 +11,12 @@ class MrvOptiswitchSSH(CiscoSSHConnection):
     def session_preparation(self):
         """Prepare the session after the connection has been established."""
         self._test_channel_read(pattern=r'[>#]')
-        self.enable()
         self.set_base_prompt()
+        self.enable()
         self.disable_paging(command="no cli-paging")
         # Clear the read buffer
         time.sleep(.3 * self.global_delay_factor)
+        self.set_base_prompt()
         self.clear_buffer()
 
     def enable(self, cmd='enable', pattern=r'#', re_flags=re.IGNORECASE):
diff --git a/netmiko/paloalto/__init__.py b/netmiko/paloalto/__init__.py
index f34f9fdfa..57262d6fe 100644
--- a/netmiko/paloalto/__init__.py
+++ b/netmiko/paloalto/__init__.py
@@ -1,4 +1,4 @@
 from __future__ import unicode_literals
-from netmiko.paloalto.paloalto_panos_ssh import PaloAltoPanosSSH
+from netmiko.paloalto.paloalto_panos import PaloAltoPanosSSH, PaloAltoPanosTelnet
 
-__all__ = ['PaloAltoPanosSSH']
+__all__ = ['PaloAltoPanosSSH', 'PaloAltoPanosTelnet']
diff --git a/netmiko/paloalto/paloalto_panos_ssh.py b/netmiko/paloalto/paloalto_panos.py
similarity index 89%
rename from netmiko/paloalto/paloalto_panos_ssh.py
rename to netmiko/paloalto/paloalto_panos.py
index 8dc0b07e2..f43c20128 100644
--- a/netmiko/paloalto/paloalto_panos_ssh.py
+++ b/netmiko/paloalto/paloalto_panos.py
@@ -4,7 +4,7 @@
 from netmiko.base_connection import BaseConnection
 
 
-class PaloAltoPanosSSH(BaseConnection):
+class PaloAltoPanosBase(BaseConnection):
     """
     Implement methods for interacting with PaloAlto devices.
 
@@ -39,16 +39,16 @@ def exit_enable_mode(self, *args, **kwargs):
 
     def check_config_mode(self, check_string=']'):
         """Checks if the device is in configuration mode or not."""
-        return super(PaloAltoPanosSSH, self).check_config_mode(check_string=check_string)
+        return super(PaloAltoPanosBase, self).check_config_mode(check_string=check_string)
 
     def config_mode(self, config_command='configure'):
         """Enter configuration mode."""
-        return super(PaloAltoPanosSSH, self).config_mode(config_command=config_command)
+        return super(PaloAltoPanosBase, self).config_mode(config_command=config_command)
 
     def exit_config_mode(self, exit_config='exit', pattern=r'>'):
         """Exit configuration mode."""
-        return super(PaloAltoPanosSSH, self).exit_config_mode(exit_config=exit_config,
-                                                              pattern=pattern)
+        return super(PaloAltoPanosBase, self).exit_config_mode(exit_config=exit_config,
+                                                               pattern=pattern)
 
     def commit(self, force=False, partial=False, device_and_network=False,
                policy_and_objects=False, vsys='', no_vsys=False, delay_factor=.1):
@@ -146,4 +146,12 @@ def send_command_expect(self, *args, **kwargs):
     def send_command(self, *args, **kwargs):
         """Palo Alto requires an extra delay"""
         kwargs['delay_factor'] = kwargs.get('delay_factor', 2.5)
-        return super(PaloAltoPanosSSH, self).send_command(*args, **kwargs)
+        return super(PaloAltoPanosBase, self).send_command(*args, **kwargs)
+
+
+class PaloAltoPanosSSH(PaloAltoPanosBase):
+    pass
+
+
+class PaloAltoPanosTelnet(PaloAltoPanosBase):
+    pass
diff --git a/netmiko/rad/__init__.py b/netmiko/rad/__init__.py
new file mode 100644
index 000000000..22a125b3b
--- /dev/null
+++ b/netmiko/rad/__init__.py
@@ -0,0 +1,5 @@
+from __future__ import unicode_literals
+from netmiko.rad.rad_etx import RadETXSSH
+from netmiko.rad.rad_etx import RadETXTelnet
+
+__all__ = ['RadETXSSH', 'RadETXTelnet']
diff --git a/netmiko/rad/rad_etx.py b/netmiko/rad/rad_etx.py
new file mode 100644
index 000000000..0aeb62153
--- /dev/null
+++ b/netmiko/rad/rad_etx.py
@@ -0,0 +1,85 @@
+from __future__ import unicode_literals
+from __future__ import print_function
+import time
+from netmiko.base_connection import BaseConnection
+
+
+class RadETXBase(BaseConnection):
+    """RAD ETX Support, Tested on RAD 203AX, 205A and 220A."""
+    def session_preparation(self):
+        self._test_channel_read()
+        self.set_base_prompt()
+        self.disable_paging(command='config term length 0')
+        # Clear the read buffer
+        time.sleep(.3 * self.global_delay_factor)
+        self.clear_buffer()
+
+    def save_config(self, cmd='admin save', confirm=False, confirm_response=''):
+        """Saves Config Using admin save."""
+        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
+
+    def check_enable_mode(self, *args, **kwargs):
+        """The Rad ETX software does not have an enable."""
+        pass
+
+    def enable(self, *args, **kwargs):
+        """The Rad ETX software does not have an enable."""
+        pass
+
+    def exit_enable_mode(self, *args, **kwargs):
+        """The Rad ETX software does not have an enable."""
+        pass
+
+    def config_mode(self, config_command='config', pattern='>config'):
+        """Enter into configuration mode on remote device."""
+        return super(RadETXBase, self).config_mode(config_command=config_command,
+                                                   pattern=pattern)
+
+    def check_config_mode(self, check_string='>config', pattern=''):
+        """
+        Checks if the device is in configuration mode or not.
+
+        Rad config starts with baseprompt>config.
+        """
+        return super(RadETXBase, self).check_config_mode(check_string=check_string,
+                                                         pattern=pattern)
+
+    def exit_config_mode(self, exit_config='exit all', pattern='#'):
+        """Exit from configuration mode."""
+        return super(RadETXBase, self).exit_config_mode(exit_config=exit_config,
+                                                        pattern=pattern)
+
+
+class RadETXSSH(RadETXBase):
+    """RAD ETX SSH Support."""
+    def __init__(self, **kwargs):
+        # Found that a global_delay_factor of 2 is needed at minimum for SSH to the Rad ETX.
+        kwargs.setdefault('global_delay_factor', 2)
+        return super(RadETXSSH, self).__init__(**kwargs)
+
+
+class RadETXTelnet(RadETXBase):
+    """RAD ETX Telnet Support."""
+    def telnet_login(self, username_pattern=r"(?:user>)",
+                     alt_prompt_term=r"#\s*$", **kwargs):
+        """
+        RAD presents with the following on login
+
+        user>
+
+        password> ****
+        """
+        self.TELNET_RETURN = self.RETURN
+        return super(RadETXTelnet,
+                     self).telnet_login(username_pattern=username_pattern,
+                                        alt_prompt_terminator=alt_prompt_term, **kwargs)
diff --git a/netmiko/snmp_autodetect.py b/netmiko/snmp_autodetect.py
index 29d819a2f..9cbd0fb16 100644
--- a/netmiko/snmp_autodetect.py
+++ b/netmiko/snmp_autodetect.py
@@ -29,6 +29,7 @@
     raise ImportError("pysnmp not installed; please install it: 'pip install pysnmp'")
 
 from netmiko.ssh_dispatcher import CLASS_MAPPER
+from netmiko.py23_compat import text_type
 
 
 # Higher priority indicates a better match.
@@ -42,6 +43,9 @@
     'hp_comware': {"oid": ".1.3.6.1.2.1.1.1.0",
                    "expr": re.compile(r".*HP Comware.*", re.IGNORECASE),
                    "priority": 99},
+    'hp_procurve': {"oid": ".1.3.6.1.2.1.1.1.0",
+                    "expr": re.compile(r".ProCurve", re.IGNORECASE),
+                    "priority": 99},
     'cisco_ios': {"oid": ".1.3.6.1.2.1.1.1.0",
                   "expr": re.compile(r".*Cisco IOS Software,.*", re.IGNORECASE),
                   "priority": 60},
@@ -60,9 +64,9 @@
     'cisco_wlc': {"oid": ".1.3.6.1.2.1.1.1.0",
                   "expr": re.compile(r".*Cisco Controller.*", re.IGNORECASE),
                   "priority": 99},
-    'f5_ltm': {"oid": ".1.3.6.1.4.1.3375.2.1.4.1.0",
-               "expr": re.compile(r".*BIG-IP.*", re.IGNORECASE),
-               "priority": 99},
+    'f5_tmsh': {"oid": ".1.3.6.1.4.1.3375.2.1.4.1.0",
+                "expr": re.compile(r".*BIG-IP.*", re.IGNORECASE),
+                "priority": 99},
     'fortinet': {"oid": ".1.3.6.1.2.1.1.1.0",
                  "expr": re.compile(r"Forti.*", re.IGNORECASE),
                  "priority": 80},
@@ -198,7 +202,7 @@ def _get_snmpv3(self, oid):
             oid, lookupNames=True, lookupValues=True)
 
         if not error_detected and snmp_data[0][1]:
-            return str(snmp_data[0][1])
+            return text_type(snmp_data[0][1])
         return ""
 
     def _get_snmpv2c(self, oid):
@@ -224,7 +228,7 @@ def _get_snmpv2c(self, oid):
             oid, lookupNames=True, lookupValues=True)
 
         if not error_detected and snmp_data[0][1]:
-            return str(snmp_data[0][1])
+            return text_type(snmp_data[0][1])
         return ""
 
     def _get_snmp(self, oid):
diff --git a/netmiko/ssh_autodetect.py b/netmiko/ssh_autodetect.py
index 8297f704d..7f1fe9bec 100644
--- a/netmiko/ssh_autodetect.py
+++ b/netmiko/ssh_autodetect.py
@@ -77,6 +77,12 @@
         "priority": 99,
         "dispatch": "_autodetect_std",
     },
+    'cisco_asa': {
+        "cmd": "show version",
+        "search_patterns": [r"Cisco Adaptive Security Appliance", r"Cisco ASA"],
+        "priority": 99,
+        "dispatch": "_autodetect_std",
+    },
     'cisco_ios': {
         "cmd": "show version",
         "search_patterns": [
@@ -86,12 +92,6 @@
         "priority": 99,
         "dispatch": "_autodetect_std",
     },
-    'cisco_asa': {
-        "cmd": "show version",
-        "search_patterns": [r"Cisco Adaptive Security Appliance", r"Cisco ASA"],
-        "priority": 99,
-        "dispatch": "_autodetect_std",
-    },
     'cisco_nxos': {
         "cmd": "show version",
         "search_patterns": [r"Cisco Nexus Operating System", r"NX-OS"],
@@ -104,6 +104,30 @@
         "priority": 99,
         "dispatch": "_autodetect_std",
     },
+    'dell_force10': {
+        "cmd": "show version",
+        "search_patterns": [r"S4048-ON"],
+        "priority": 99,
+        "dispatch": "_autodetect_std",
+    },
+    'dell_os10': {
+        "cmd": "show version",
+        "search_patterns": [r"Dell EMC Networking OS10-Enterprise"],
+        "priority": 99,
+        "dispatch": "_autodetect_std",
+    },
+    'f5_tmsh': {
+        "cmd": "show sys version",
+        "search_patterns": [r"BIG-IP"],
+        "priority": 99,
+        "dispatch": "_autodetect_std",
+    },
+    'f5_linux': {
+        "cmd": "cat /etc/issue",
+        "search_patterns": [r"BIG-IP"],
+        "priority": 99,
+        "dispatch": "_autodetect_std",
+    },
     'huawei': {
         "cmd": "display version",
         "search_patterns": [
@@ -123,18 +147,12 @@
         "priority": 99,
         "dispatch": "_autodetect_std",
     },
-    'dell_force10': {
-        "cmd": "show version",
-        "search_patterns": [r"S4048-ON"],
-        "priority": 99,
-        "dispatch": "_autodetect_std",
-    },
-    'dell_os10': {
-        "cmd": "show version",
-        "search_patterns": [r"Dell EMC Networking OS10-Enterprise"],
+    'linux': {
+        "cmd": "uname -a",
+        "search_patterns": [r"Linux"],
         "priority": 99,
         "dispatch": "_autodetect_std",
-    },
+    }
 }
 
 
@@ -274,7 +292,9 @@ def _autodetect_std(self, cmd="", search_patterns=None, re_flags=re.I, priority=
             r'% Invalid input detected',
             r'syntax error, expecting',
             r'Error: Unrecognized command',
-            r'%Error'
+            r'%Error',
+            r'command not found',
+            r'Syntax Error: unexpected argument',
         ]
         if not cmd or not search_patterns:
             return 0
diff --git a/netmiko/ssh_dispatcher.py b/netmiko/ssh_dispatcher.py
index 987def376..9837a402d 100644
--- a/netmiko/ssh_dispatcher.py
+++ b/netmiko/ssh_dispatcher.py
@@ -9,11 +9,6 @@
 from netmiko.arista import AristaFileTransfer
 from netmiko.apresia import ApresiaAeosSSH, ApresiaAeosTelnet
 from netmiko.aruba import ArubaSSH
-from netmiko.avaya import AvayaErsSSH
-from netmiko.avaya import AvayaVspSSH
-from netmiko.brocade import BrocadeNetironSSH
-from netmiko.brocade import BrocadeNetironTelnet
-from netmiko.brocade import BrocadeNosSSH
 from netmiko.calix import CalixB6SSH, CalixB6Telnet
 from netmiko.checkpoint import CheckPointGaiaSSH
 from netmiko.ciena import CienaSaosSSH
@@ -26,6 +21,8 @@
 from netmiko.cisco import CiscoXrSSH, CiscoXrFileTransfer
 from netmiko.citrix import NetscalerSSH
 from netmiko.coriant import CoriantSSH
+from netmiko.dell import DellDNOS6SSH
+from netmiko.dell import DellDNOS6Telnet
 from netmiko.dell import DellForce10SSH
 from netmiko.dell import DellOS10SSH, DellOS10FileTransfer
 from netmiko.dell import DellPowerConnectSSH
@@ -33,13 +30,21 @@
 from netmiko.dell import DellIsilonSSH
 from netmiko.eltex import EltexSSH
 from netmiko.enterasys import EnterasysSSH
-from netmiko.extreme import ExtremeSSH
+from netmiko.extreme import ExtremeErsSSH
+from netmiko.extreme import ExtremeExosSSH
+from netmiko.extreme import ExtremeExosTelnet
+from netmiko.extreme import ExtremeNetironSSH
+from netmiko.extreme import ExtremeNetironTelnet
+from netmiko.extreme import ExtremeNosSSH
+from netmiko.extreme import ExtremeSlxSSH
+from netmiko.extreme import ExtremeVspSSH
 from netmiko.extreme import ExtremeWingSSH
-from netmiko.extreme import ExtremeTelnet
-from netmiko.f5 import F5LtmSSH
+from netmiko.f5 import F5TmshSSH
+from netmiko.f5 import F5LinuxSSH
 from netmiko.fortinet import FortinetSSH
 from netmiko.hp import HPProcurveSSH, HPProcurveTelnet, HPComwareSSH, HPComwareTelnet
 from netmiko.huawei import HuaweiSSH, HuaweiVrpv8SSH
+from netmiko.ipinfusion import IpInfusionOcNOSSSH, IpInfusionOcNOSTelnet
 from netmiko.juniper import JuniperSSH, JuniperTelnet
 from netmiko.juniper import JuniperFileTransfer
 from netmiko.linux import LinuxSSH, LinuxFileTransfer
@@ -48,8 +53,11 @@
 from netmiko.netapp import NetAppcDotSSH
 from netmiko.ovs import OvsLinuxSSH
 from netmiko.paloalto import PaloAltoPanosSSH
+from netmiko.paloalto import PaloAltoPanosTelnet
 from netmiko.pluribus import PluribusSSH
 from netmiko.quanta import QuantaMeshSSH
+from netmiko.rad import RadETXSSH
+from netmiko.rad import RadETXTelnet
 from netmiko.ruckus import RuckusFastironSSH
 from netmiko.ruckus import RuckusFastironTelnet
 from netmiko.terminal_server import TerminalServerSSH
@@ -67,12 +75,12 @@
     'apresia_aeos': ApresiaAeosSSH,
     'arista_eos': AristaSSH,
     'aruba_os': ArubaSSH,
-    'avaya_ers': AvayaErsSSH,
-    'avaya_vsp': AvayaVspSSH,
+    'avaya_ers': ExtremeErsSSH,
+    'avaya_vsp': ExtremeVspSSH,
     'brocade_fastiron': RuckusFastironSSH,
-    'brocade_netiron': BrocadeNetironSSH,
-    'brocade_nos': BrocadeNosSSH,
-    'brocade_vdx': BrocadeNosSSH,
+    'brocade_netiron': ExtremeNetironSSH,
+    'brocade_nos': ExtremeNosSSH,
+    'brocade_vdx': ExtremeNosSSH,
     'brocade_vyos': VyOSSSH,
     'checkpoint_gaia': CheckPointGaiaSSH,
     'calix_b6': CalixB6SSH,
@@ -86,21 +94,34 @@
     'cisco_xe': CiscoIosSSH,
     'cisco_xr': CiscoXrSSH,
     'coriant': CoriantSSH,
+    'dell_dnos9': DellForce10SSH,
     'dell_force10': DellForce10SSH,
+    'dell_os6': DellDNOS6SSH,
+    'dell_os9': DellForce10SSH,
     'dell_os10': DellOS10SSH,
     'dell_powerconnect': DellPowerConnectSSH,
     'dell_isilon': DellIsilonSSH,
     'eltex': EltexSSH,
     'enterasys': EnterasysSSH,
-    'extreme': ExtremeSSH,
+    'extreme': ExtremeExosSSH,
+    'extreme_ers': ExtremeErsSSH,
+    'extreme_exos': ExtremeExosSSH,
+    'extreme_netiron': ExtremeNetironSSH,
+    'extreme_nos': ExtremeNosSSH,
+    'extreme_slx': ExtremeSlxSSH,
+    'extreme_vdx': ExtremeNosSSH,
+    'extreme_vsp': ExtremeVspSSH,
     'extreme_wing': ExtremeWingSSH,
-    'f5_ltm': F5LtmSSH,
+    'f5_ltm': F5TmshSSH,
+    'f5_tmsh': F5TmshSSH,
+    'f5_linux': F5LinuxSSH,
     'fortinet': FortinetSSH,
     'generic_termserver': TerminalServerSSH,
     'hp_comware': HPComwareSSH,
     'hp_procurve': HPProcurveSSH,
     'huawei': HuaweiSSH,
     'huawei_vrpv8': HuaweiVrpv8SSH,
+    'ipinfusion_ocnos': IpInfusionOcNOSSSH,
     'juniper': JuniperSSH,
     'juniper_junos': JuniperSSH,
     'linux': LinuxSSH,
@@ -112,6 +133,7 @@
     'paloalto_panos': PaloAltoPanosSSH,
     'pluribus': PluribusSSH,
     'quanta_mesh': QuantaMeshSSH,
+    'rad_etx': RadETXSSH,
     'ruckus_fastiron': RuckusFastironSSH,
     'ubiquiti_edge': UbiquitiEdgeSSH,
     'ubiquiti_edgeswitch': UbiquitiEdgeSSH,
@@ -147,18 +169,24 @@
 FILE_TRANSFER_MAP = new_mapper
 
 # Add telnet drivers
-CLASS_MAPPER['brocade_fastiron_telnet'] = RuckusFastironTelnet
-CLASS_MAPPER['brocade_netiron_telnet'] = BrocadeNetironTelnet
-CLASS_MAPPER['cisco_ios_telnet'] = CiscoIosTelnet
 CLASS_MAPPER['apresia_aeos_telnet'] = ApresiaAeosTelnet
 CLASS_MAPPER['arista_eos_telnet'] = AristaTelnet
-CLASS_MAPPER['hp_procurve_telnet'] = HPProcurveTelnet
-CLASS_MAPPER['hp_comware_telnet'] = HPComwareTelnet
-CLASS_MAPPER['juniper_junos_telnet'] = JuniperTelnet
+CLASS_MAPPER['brocade_fastiron_telnet'] = RuckusFastironTelnet
+CLASS_MAPPER['brocade_netiron_telnet'] = ExtremeNetironTelnet
 CLASS_MAPPER['calix_b6_telnet'] = CalixB6Telnet
+CLASS_MAPPER['cisco_ios_telnet'] = CiscoIosTelnet
+CLASS_MAPPER['dell_dnos6_telnet'] = DellDNOS6Telnet
 CLASS_MAPPER['dell_powerconnect_telnet'] = DellPowerConnectTelnet
+CLASS_MAPPER['extreme_telnet'] = ExtremeExosTelnet
+CLASS_MAPPER['extreme_exos_telnet'] = ExtremeExosTelnet
+CLASS_MAPPER['extreme_netiron_telnet'] = ExtremeNetironTelnet
 CLASS_MAPPER['generic_termserver_telnet'] = TerminalServerTelnet
-CLASS_MAPPER['extreme_telnet'] = ExtremeTelnet
+CLASS_MAPPER['hp_procurve_telnet'] = HPProcurveTelnet
+CLASS_MAPPER['hp_comware_telnet'] = HPComwareTelnet
+CLASS_MAPPER['ipinfusion_ocnos_telnet'] = IpInfusionOcNOSTelnet
+CLASS_MAPPER['juniper_junos_telnet'] = JuniperTelnet
+CLASS_MAPPER['paloalto_panos_telnet'] = PaloAltoPanosTelnet
+CLASS_MAPPER['rad_etx_telnet'] = RadETXTelnet
 CLASS_MAPPER['ruckus_fastiron_telnet'] = RuckusFastironTelnet
 
 # Add serial drivers
@@ -205,7 +233,7 @@ def redispatch(obj, device_type, session_prep=True):
     obj.device_type = device_type
     obj.__class__ = new_class
     if session_prep:
-        obj.session_preparation()
+        obj._try_session_preparation()
 
 
 def FileTransfer(*args, **kwargs):
diff --git a/netmiko/utilities.py b/netmiko/utilities.py
index fd7d3896d..9820f739d 100644
--- a/netmiko/utilities.py
+++ b/netmiko/utilities.py
@@ -8,6 +8,7 @@
 import serial.tools.list_ports
 from netmiko._textfsm import _clitable as clitable
 from netmiko._textfsm._clitable import CliTableError
+from netmiko.py23_compat import text_type
 
 
 # Dictionary mapping 'show run' for vendors with different command
@@ -15,6 +16,13 @@
     'juniper': 'show configuration',
     'juniper_junos': 'show configuration',
     'extreme': 'show configuration',
+    'extreme_ers': 'show running-config',
+    'extreme_exos': 'show configuration',
+    'extreme_netiron': 'show running-config',
+    'extreme_nos': 'show running-config',
+    'extreme_slx': 'show running-config',
+    'extreme_vdx': 'show running-config',
+    'extreme_vsp': 'show running-config',
     'extreme_wing': 'show running-config',
     'hp_comware': 'display current-configuration',
     'huawei': 'display current-configuration',
@@ -150,19 +158,25 @@ def find_netmiko_dir():
     return (netmiko_base_dir, netmiko_full_dir)
 
 
-def write_bytes(out_data):
+def write_bytes(out_data, encoding='ascii'):
     """Write Python2 and Python3 compatible byte stream."""
     if sys.version_info[0] >= 3:
         if isinstance(out_data, type(u'')):
-            return out_data.encode('ascii', 'ignore')
+            if encoding == 'utf-8':
+                return out_data.encode('utf-8')
+            else:
+                return out_data.encode('ascii', 'ignore')
         elif isinstance(out_data, type(b'')):
             return out_data
     else:
         if isinstance(out_data, type(u'')):
-            return out_data.encode('ascii', 'ignore')
+            if encoding == 'utf-8':
+                return out_data.encode('utf-8')
+            else:
+                return out_data.encode('ascii', 'ignore')
         elif isinstance(out_data, type(str(''))):
             return out_data
-    msg = "Invalid value for out_data neither unicode nor byte string: {0}".format(out_data)
+    msg = "Invalid value for out_data neither unicode nor byte string: {}".format(out_data)
     raise ValueError(msg)
 
 
@@ -176,7 +190,7 @@ def check_serial_port(name):
         msg += "available devices are: "
         ports = list(serial.tools.list_ports.comports())
         for p in ports:
-            msg += "{},".format(str(p))
+            msg += "{},".format(text_type(p))
         raise ValueError(msg)
 
 
diff --git a/setup.py b/setup.py
index 3ad8fda75..6648c02a8 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@
 
 
 requirements = [
-    'paramiko>=2.0.0',
+    'paramiko>=2.4.1',
     'scp>=0.10.0',
     'pyyaml',
     'pyserial',
diff --git a/tests/etc/commands.yml.example b/tests/etc/commands.yml.example
index 4715ee8d1..b41f8852a 100644
--- a/tests/etc/commands.yml.example
+++ b/tests/etc/commands.yml.example
@@ -9,7 +9,10 @@ cisco_ios:
     - "no logging console"
     - "logging buffered 20010"      # something you can verify has changed
   config_verification: "show run | inc logging buffer"
-  config_file: "cisco_ios_commands.txt"
+  config_file: 'cisco_ios_commands.txt'
+  save_config_cmd: 'copy run start'
+  save_config_confirm: True
+  save_config_response: ''
 
 cisco_asa:
   version: "show version"
@@ -179,3 +182,29 @@ calix_b6_ssh:
     - "access-list ethernet 999 permit ip"
     - "access-list ethernet 999 permit arp"
   config_verification: "find running-config 999"
+
+ipinfusion_ocnos:
+  version: "show version"
+  basic: "show ip interface eth0 brief"
+  extended_output: "show ip interface brief"   # requires paging to be disabled
+  config:
+    - "logging  level ospf 4"      # base command
+    - "no logging level ospf"
+    - "logging level ospf 5"      # something you can verify has changed
+  config_verification: "show logging level ospf"
+  save_config_cmd: 'write'
+  save_config_confirm: False
+  save_config_response: "[OK]"
+
+ipinfusion_ocnos_telnet:
+  version: "show version"
+  basic: "show ip interface eth0 brief"
+  extended_output: "show ip interface brief"   # requires paging to be disabled
+  config:
+    - "logging  level ospf 4"      # base command
+    - "no logging level ospf"
+    - "logging level ospf 5"      # something you can verify has changed
+  config_verification: "show logging level ospf"
+  save_config_cmd: 'write'
+  save_config_confirm: False
+  save_config_response: "[OK]"
diff --git a/tests/etc/responses.yml.example b/tests/etc/responses.yml.example
index d900fbc6e..767d63f2a 100644
--- a/tests/etc/responses.yml.example
+++ b/tests/etc/responses.yml.example
@@ -8,6 +8,7 @@ cisco_ios:
   version_banner: "Cisco IOS Software"
   multiple_line_output: "Configuration register is"
   file_check_cmd: "logging buffered 8880"
+  save_config: 'OK'
 
 juniper:
   base_prompt: pyclass@pynet-jnpr-srx1
@@ -132,3 +133,25 @@ calix_b6_ssh:
   multiple_line_output: "rtcPwrUptimeTotal"
   cmd_response_init: "Building configuration...    Done"
   cmd_response_final: "access-list ethernet 999 permit ip"
+
+ipinfusion_ocnos:
+  base_prompt: rtr1
+  router_prompt: rtr1>
+  enable_prompt: rtr1#
+  interface_ip: 10.12.39.34
+  version_banner: "Software Product: OcNOS"
+  multiple_line_output: "lo                   127.0.0.1"
+  cmd_response_init: "ospfd                   2                           4"
+  cmd_response_final: "ospfd                   2                           5"
+  save_config: '[OK]'
+
+ipinfusion_ocnos_telnet:
+  base_prompt: rtr1
+  router_prompt: rtr1>
+  enable_prompt: rtr1#
+  interface_ip: 10.12.39.34
+  version_banner: "Software Product: OcNOS"
+  multiple_line_output: "lo                   127.0.0.1"
+  cmd_response_init: "ospfd                   2                           4"
+  cmd_response_final: "ospfd                   2                           5"
+  save_config: '[OK]'
diff --git a/tests/etc/test_devices.yml.example b/tests/etc/test_devices.yml.example
index d322da5be..18161b2d9 100644
--- a/tests/etc/test_devices.yml.example
+++ b/tests/etc/test_devices.yml.example
@@ -119,3 +119,18 @@ calix_b6_ssh:
   username: cli
   password: occam
   secret: razor
+
+ipinfusion_ocnos:
+  device_type: ipinfusion_ocnos
+  ip: 10.12.39.34
+  username: ocnos
+  password: ocnos
+  secret: ocnos
+
+ipinfusion_ocnos_telnet:
+  device_type: ipinfusion_ocnos_telnet
+  ip: 10.12.39.34
+  username: ocnos
+  password: ocnos
+  secret: ocnos
+
diff --git a/tests/test_ipinfusion.sh b/tests/test_ipinfusion.sh
new file mode 100755
index 000000000..26dbffaf7
--- /dev/null
+++ b/tests/test_ipinfusion.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+RETURN_CODE=0
+
+# Exit on the first test failure and set RETURN_CODE = 1
+echo "Starting tests...good luck:" \
+&& py.test -v test_netmiko_show.py --test_device ipinfusion_ocnos \
+&& py.test -v test_netmiko_config.py --test_device ipinfusion_ocnos \
+|| RETURN_CODE=1
+
+exit $RETURN_CODE
diff --git a/tests/test_ipinfusion_telnet.sh b/tests/test_ipinfusion_telnet.sh
new file mode 100755
index 000000000..3a8a862e6
--- /dev/null
+++ b/tests/test_ipinfusion_telnet.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+RETURN_CODE=0
+
+# Exit on the first test failure and set RETURN_CODE = 1
+echo "Starting tests...good luck:" \
+&& py.test -v test_netmiko_show.py --test_device ipinfusion_ocnos_telnet \
+&& py.test -v test_netmiko_config.py --test_device ipinfusion_ocnos_telnet \
+|| RETURN_CODE=1
+
+exit $RETURN_CODE
diff --git a/tests/test_netmiko_config.py b/tests/test_netmiko_config.py
index 275e3e96d..237627f95 100755
--- a/tests/test_netmiko_config.py
+++ b/tests/test_netmiko_config.py
@@ -1,19 +1,4 @@
 #!/usr/bin/env python
-"""
-This module runs tests against Cisco IOS devices.
-
-setup_module: setup variables for later use.
-
-test_ssh_connect: verify ssh connectivity
-test_enable_mode: verify enter enable mode
-test_config_mode: verify enter config mode
-test_exit_config_mode: verify exit config mode
-test_command_set: verify sending a set of config commands
-test_commands_from_file: verify sending a set of config commands from a file
-test_disconnect: cleanly disconnect the SSH session
-
-"""
-
 from __future__ import print_function
 from __future__ import unicode_literals
 
@@ -106,5 +91,3 @@ def test_disconnect(net_connect, commands, expected_responses):
     Terminate the SSH session
     '''
     net_connect.disconnect()
-
-
diff --git a/tests/test_netmiko_save.py b/tests/test_netmiko_save.py
new file mode 100755
index 000000000..9be4acdae
--- /dev/null
+++ b/tests/test_netmiko_save.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+from __future__ import print_function
+from __future__ import unicode_literals
+
+
+def test_save_base(net_connect, commands, expected_responses):
+    '''
+    Test save config with no options.
+    '''
+    save_verify = expected_responses['save_config']
+
+    cmd_response = net_connect.save_config()
+    assert save_verify in cmd_response
+
+def test_save_confirm(net_connect, commands, expected_responses):
+    '''
+    Test save config with the confirm parameter.
+    '''
+    confirm = commands['save_config_confirm']
+    save_verify = expected_responses['save_config']
+
+    cmd_response = net_connect.save_config(confirm)
+    assert save_verify in cmd_response
+
+def test_save_response(net_connect, commands, expected_responses):
+    '''
+    Test save config with the confirm response parameter.
+    '''
+    confirm_response = commands['save_config_response']
+    save_verify = expected_responses['save_config']
+
+    cmd_response = net_connect.save_config(confirm_response=confirm_response)
+    assert save_verify in cmd_response
+
+def test_save_cmd(net_connect, commands, expected_responses):
+    '''
+    Test save config with cmd parameter.
+    '''
+    cmd = commands['save_config_cmd']
+    save_verify = expected_responses['save_config']
+
+    cmd_response = net_connect.save_config(cmd=cmd)
+    assert save_verify in cmd_response
+
+def test_save_confirm_response(net_connect, commands, expected_responses):
+    '''
+    Test save config with confirm and confirm response parameters
+    '''
+    confirm = commands['save_config_confirm']
+    confirm_response = commands['save_config_response']
+    save_verify = expected_responses['save_config']
+
+    cmd_response = net_connect.save_config(confirm=confirm, 
+                                          confirm_response=confirm_response)
+    assert save_verify in cmd_response    
+
+def test_save_all(net_connect, commands, expected_responses):
+    '''
+    Test the save config method with all additional parameters.
+    '''
+    cmd = commands['save_config_cmd'] 
+    confirm = commands['save_config_confirm']
+    confirm_response = commands['save_config_response']
+    save_verify = expected_responses['save_config']
+
+    cmd_response = net_connect.save_config(cmd=cmd, confirm=confirm, 
+                                           confirm_response=confirm_response)
+    assert save_verify in cmd_response
+
+def test_disconnect(net_connect, commands, expected_responses):
+    '''
+    Terminate the SSH session
+    '''
+    net_connect.disconnect()
diff --git a/tests/test_netmiko_scp.py b/tests/test_netmiko_scp.py
index ad5c938fb..965362dc6 100755
--- a/tests/test_netmiko_scp.py
+++ b/tests/test_netmiko_scp.py
@@ -43,7 +43,7 @@ def test_verify_space_available_put(scp_fixture):
     ssh_conn, scp_transfer = scp_fixture
     assert scp_transfer.verify_space_available() == True
     # intentional make there not be enough space available
-    scp_transfer.file_size = 10000000000
+    scp_transfer.file_size = 100000000000
     assert scp_transfer.verify_space_available() == False
 
 def test_remote_file_size(scp_fixture):
diff --git a/tests/test_suite_alt.sh b/tests/test_suite_alt.sh
index c84b6e424..82f8f75d2 100755
--- a/tests/test_suite_alt.sh
+++ b/tests/test_suite_alt.sh
@@ -44,10 +44,6 @@ echo "Starting tests...good luck:" \
 && py.test -v test_netmiko_show.py --test_device hp_procurve \
 && py.test -v test_netmiko_config.py --test_device hp_procurve \
 \
-&& echo "HP Comware7" \
-&& py.test -v test_netmiko_show.py --test_device hp_comware \
-&& py.test -v test_netmiko_config.py --test_device hp_comware \
-\
 && echo "Juniper" \
 && py.test -v test_netmiko_scp.py --test_device juniper_srx \
 && py.test -v test_netmiko_show.py --test_device juniper_srx \
@@ -85,3 +81,8 @@ echo "Starting tests...good luck:" \
 || RETURN_CODE=1
 
 exit $RETURN_CODE
+
+# && echo "HP Comware7" \
+# && py.test -v test_netmiko_show.py --test_device hp_comware \
+# && py.test -v test_netmiko_config.py --test_device hp_comware \
+# \