'Creates a tunnel between two hosts. Like ssh -L <LOCAL_PORT>:host:<REMOTE_PORT>.
Remember to close() the returned "tunnel" object in order to clean up
after yourself when you are done with the tunnel.
:param local_port:
:type local_port: int
:param remote_port:
:type remote_port: int
:param remote_host:
:type remote_host: str
:return:'

@contextmanager
def create_tunnel(self, local_port, remote_port=None, remote_host='localhost'):

    import subprocess
    self.get_conn()
    tunnel_host = '{0}:{1}:{2}'.format(local_port, remote_host, remote_port)
    ssh_cmd = ['ssh', '{0}@{1}'.format(self.username, self.remote_host), '-o', 'ControlMaster=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', 'StrictHostKeyChecking=no']
    ssh_tunnel_cmd = ['-L', tunnel_host, 'echo    -n    ready    &&    cat']
    ssh_cmd += ssh_tunnel_cmd
    logging.debug('creating    tunnel    with    cmd:    {0}'.format(ssh_cmd))
    proc = subprocess.Popen(ssh_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    ready = proc.stdout.read(5)
    assert (ready == 'ready'), "Did    not    get    'ready'    from    remote,    got    '{0}'    instead".format(ready)
    (yield)
    proc.communicate()
    assert (proc.returncode == 0), 'Tunnel    process    did    unclean    exit    (returncode    {}'.format(proc.returncode)
