We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
SSHChannel fails with host-based authentication
Systems using host-based authentication (without a key or a password) fail with:
```
paramiko.ssh_exception.SSHException: No authentication methods available
```

Reported by @jmoon1506

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `parsl/channels/ssh/ssh.py`
Content:
```
1 import errno
2 import logging
3 import os
4 
5 import paramiko
6 from parsl.channels.base import Channel
7 from parsl.channels.errors import *
8 from parsl.utils import RepresentationMixin
9 
10 logger = logging.getLogger(__name__)
11 
12 
13 class SSHChannel(Channel, RepresentationMixin):
14     ''' SSH persistent channel. This enables remote execution on sites
15     accessible via ssh. It is assumed that the user has setup host keys
16     so as to ssh to the remote host. Which goes to say that the following
17     test on the commandline should work :
18 
19     >>> ssh <username>@<hostname>
20 
21     '''
22 
23     def __init__(self, hostname, username=None, password=None, script_dir=None, envs=None, **kwargs):
24         ''' Initialize a persistent connection to the remote system.
25         We should know at this point whether ssh connectivity is possible
26 
27         Args:
28             - hostname (String) : Hostname
29 
30         KWargs:
31             - username (string) : Username on remote system
32             - password (string) : Password for remote system
33             - script_dir (string) : Full path to a script dir where
34               generated scripts could be sent to.
35             - envs (dict) : A dictionary of environment variables to be set when executing commands
36 
37         Raises:
38         '''
39 
40         self.hostname = hostname
41         self.username = username
42         self.password = password
43         self.kwargs = kwargs
44         self.script_dir = script_dir
45 
46         self.ssh_client = paramiko.SSHClient()
47         self.ssh_client.load_system_host_keys()
48         self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
49 
50         self.envs = {}
51         if envs is not None:
52             self.envs = envs
53 
54         try:
55             self.ssh_client.connect(
56                 hostname,
57                 username=username,
58                 password=password,
59                 allow_agent=True
60             )
61             t = self.ssh_client.get_transport()
62             self.sftp_client = paramiko.SFTPClient.from_transport(t)
63 
64         except paramiko.BadHostKeyException as e:
65             raise BadHostKeyException(e, self.hostname)
66 
67         except paramiko.AuthenticationException as e:
68             raise AuthException(e, self.hostname)
69 
70         except paramiko.SSHException as e:
71             raise SSHException(e, self.hostname)
72 
73         except Exception as e:
74             raise SSHException(e, self.hostname)
75 
76     def prepend_envs(self, cmd, env={}):
77         env.update(self.envs)
78 
79         if len(env.keys()) > 0:
80             env_vars = ' '.join(['{}={}'.format(key, value) for key, value in env.items()])
81             return 'env {0} {1}'.format(env_vars, cmd)
82         return cmd
83 
84     def execute_wait(self, cmd, walltime=2, envs={}):
85         ''' Synchronously execute a commandline string on the shell.
86 
87         Args:
88             - cmd (string) : Commandline string to execute
89             - walltime (int) : walltime in seconds, this is not really used now.
90 
91         Kwargs:
92             - envs (dict) : Dictionary of env variables
93 
94         Returns:
95             - retcode : Return code from the execution, -1 on fail
96             - stdout  : stdout string
97             - stderr  : stderr string
98 
99         Raises:
100         None.
101         '''
102 
103         # Execute the command
104         stdin, stdout, stderr = self.ssh_client.exec_command(
105             self.prepend_envs(cmd, envs), bufsize=-1, timeout=walltime
106         )
107         # Block on exit status from the command
108         exit_status = stdout.channel.recv_exit_status()
109         return exit_status, stdout.read().decode("utf-8"), stderr.read().decode("utf-8")
110 
111     def execute_no_wait(self, cmd, walltime=2, envs={}):
112         ''' Execute asynchronousely without waiting for exitcode
113 
114         Args:
115             - cmd (string): Commandline string to be executed on the remote side
116             - walltime (int): timeout to exec_command
117 
118         KWargs:
119             - envs (dict): A dictionary of env variables
120 
121         Returns:
122             - None, stdout (readable stream), stderr (readable stream)
123 
124         Raises:
125             - ChannelExecFailed (reason)
126         '''
127 
128         # Execute the command
129         stdin, stdout, stderr = self.ssh_client.exec_command(
130             self.prepend_envs(cmd, envs), bufsize=-1, timeout=walltime
131         )
132         # Block on exit status from the command
133         return None, stdout, stderr
134 
135     def push_file(self, local_source, remote_dir):
136         ''' Transport a local file to a directory on a remote machine
137 
138         Args:
139             - local_source (string): Path
140             - remote_dir (string): Remote path
141 
142         Returns:
143             - str: Path to copied file on remote machine
144 
145         Raises:
146             - BadScriptPath : if script path on the remote side is bad
147             - BadPermsScriptPath : You do not have perms to make the channel script dir
148             - FileCopyException : FileCopy failed.
149 
150         '''
151         remote_dest = remote_dir + '/' + os.path.basename(local_source)
152 
153         try:
154             self.makedirs(remote_dir, exist_ok=True)
155         except IOError as e:
156             logger.exception("Pushing {0} to {1} failed".format(local_source, remote_dir))
157             if e.errno == 2:
158                 raise BadScriptPath(e, self.hostname)
159             elif e.errno == 13:
160                 raise BadPermsScriptPath(e, self.hostname)
161             else:
162                 logger.exception("File push failed due to SFTP client failure")
163                 raise FileCopyException(e, self.hostname)
164         try:
165             self.sftp_client.put(local_source, remote_dest, confirm=True)
166             # Set perm because some systems require the script to be executable
167             self.sftp_client.chmod(remote_dest, 0o777)
168         except Exception as e:
169             logger.exception("File push from local source {} to remote destination {} failed".format(
170                 local_source, remote_dest))
171             raise FileCopyException(e, self.hostname)
172 
173         return remote_dest
174 
175     def pull_file(self, remote_source, local_dir):
176         ''' Transport file on the remote side to a local directory
177 
178         Args:
179             - remote_source (string): remote_source
180             - local_dir (string): Local directory to copy to
181 
182 
183         Returns:
184             - str: Local path to file
185 
186         Raises:
187             - FileExists : Name collision at local directory.
188             - FileCopyException : FileCopy failed.
189         '''
190 
191         local_dest = local_dir + '/' + os.path.basename(remote_source)
192 
193         try:
194             os.makedirs(local_dir)
195         except OSError as e:
196             if e.errno != errno.EEXIST:
197                 logger.exception("Failed to create script_dir: {0}".format(script_dir))
198                 raise BadScriptPath(e, self.hostname)
199 
200         # Easier to check this than to waste time trying to pull file and
201         # realize there's a problem.
202         if os.path.exists(local_dest):
203             logger.exception("Remote file copy will overwrite a local file:{0}".format(local_dest))
204             raise FileExists(None, self.hostname, filename=local_dest)
205 
206         try:
207             self.sftp_client.get(remote_source, local_dest)
208         except Exception as e:
209             logger.exception("File pull failed")
210             raise FileCopyException(e, self.hostname)
211 
212         return local_dest
213 
214     def close(self):
215         return self.ssh_client.close()
216 
217     def isdir(self, path):
218         """Return true if the path refers to an existing directory.
219 
220         Parameters
221         ----------
222         path : str
223             Path of directory on the remote side to check.
224         """
225         result = True
226         try:
227             self.sftp_client.lstat(path)
228         except FileNotFoundError:
229             result = False
230 
231         return result
232 
233     def makedirs(self, path, mode=511, exist_ok=False):
234         """Create a directory on the remote side.
235 
236         If intermediate directories do not exist, they will be created.
237 
238         Parameters
239         ----------
240         path : str
241             Path of directory on the remote side to create.
242         mode : int
243             Permissions (posix-style) for the newly-created directory.
244         exist_ok : bool
245             If False, raise an OSError if the target directory already exists.
246         """
247         if exist_ok is False and self.isdir(path):
248             raise OSError('Target directory {} already exists'.format(path))
249 
250         self.execute_wait('mkdir -p {}'.format(path))
251         self.sftp_client.chmod(path, mode)
252 
253     def abspath(self, path):
254         """Return the absolute path on the remote side.
255 
256         Parameters
257         ----------
258         path : str
259             Path for which the absolute path will be returned.
260         """
261         return self.sftp_client.normalize(path)
262 
263     @property
264     def script_dir(self):
265         return self._script_dir
266 
267     @script_dir.setter
268     def script_dir(self, value):
269         self._script_dir = value
270
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/parsl/channels/ssh/ssh.py b/parsl/channels/ssh/ssh.py
--- a/parsl/channels/ssh/ssh.py
+++ b/parsl/channels/ssh/ssh.py
@@ -10,6 +10,12 @@
 logger = logging.getLogger(__name__)
 
 
+class HostAuthSSHClient(paramiko.SSHClient):
+    def _auth(self, username, *args):
+        self._transport.auth_none(username)
+        return
+
+
 class SSHChannel(Channel, RepresentationMixin):
     ''' SSH persistent channel. This enables remote execution on sites
     accessible via ssh. It is assumed that the user has setup host keys
@@ -20,7 +26,7 @@
 
     '''
 
-    def __init__(self, hostname, username=None, password=None, script_dir=None, envs=None, **kwargs):
+    def __init__(self, hostname, username=None, password=None, script_dir=None, envs=None, host_auth=False, **kwargs):
         ''' Initialize a persistent connection to the remote system.
         We should know at this point whether ssh connectivity is possible
 
@@ -42,8 +48,12 @@
         self.password = password
         self.kwargs = kwargs
         self.script_dir = script_dir
+        self.host_auth = host_auth
 
-        self.ssh_client = paramiko.SSHClient()
+        if host_auth:
+            self.ssh_client = HostAuthSSHClient()
+        else:
+            self.ssh_client = paramiko.SSHClient()
         self.ssh_client.load_system_host_keys()
         self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

{"golden_diff": "diff --git a/parsl/channels/ssh/ssh.py b/parsl/channels/ssh/ssh.py\n--- a/parsl/channels/ssh/ssh.py\n+++ b/parsl/channels/ssh/ssh.py\n@@ -10,6 +10,12 @@\n logger = logging.getLogger(__name__)\n \n \n+class HostAuthSSHClient(paramiko.SSHClient):\n+    def _auth(self, username, *args):\n+        self._transport.auth_none(username)\n+        return\n+\n+\n class SSHChannel(Channel, RepresentationMixin):\n     ''' SSH persistent channel. This enables remote execution on sites\n     accessible via ssh. It is assumed that the user has setup host keys\n@@ -20,7 +26,7 @@\n \n     '''\n \n-    def __init__(self, hostname, username=None, password=None, script_dir=None, envs=None, **kwargs):\n+    def __init__(self, hostname, username=None, password=None, script_dir=None, envs=None, host_auth=False, **kwargs):\n         ''' Initialize a persistent connection to the remote system.\n         We should know at this point whether ssh connectivity is possible\n \n@@ -42,8 +48,12 @@\n         self.password = password\n         self.kwargs = kwargs\n         self.script_dir = script_dir\n+        self.host_auth = host_auth\n \n-        self.ssh_client = paramiko.SSHClient()\n+        if host_auth:\n+            self.ssh_client = HostAuthSSHClient()\n+        else:\n+            self.ssh_client = paramiko.SSHClient()\n         self.ssh_client.load_system_host_keys()\n         self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())\n", "issue": "SSHChannel fails with host-based authentication\nSystems using host-based authentication (without a key or a password) fail with:\r\n```\r\nparamiko.ssh_exception.SSHException: No authentication methods available\r\n```\r\n\r\nReported by @jmoon1506\n", "before_files": [{"content": "import errno\nimport logging\nimport os\n\nimport paramiko\nfrom parsl.channels.base import Channel\nfrom parsl.channels.errors import *\nfrom parsl.utils import RepresentationMixin\n\nlogger = logging.getLogger(__name__)\n\n\nclass SSHChannel(Channel, RepresentationMixin):\n    ''' SSH persistent channel. This enables remote execution on sites\n    accessible via ssh. It is assumed that the user has setup host keys\n    so as to ssh to the remote host. Which goes to say that the following\n    test on the commandline should work :\n\n    >>> ssh <username>@<hostname>\n\n    '''\n\n    def __init__(self, hostname, username=None, password=None, script_dir=None, envs=None, **kwargs):\n        ''' Initialize a persistent connection to the remote system.\n        We should know at this point whether ssh connectivity is possible\n\n        Args:\n            - hostname (String) : Hostname\n\n        KWargs:\n            - username (string) : Username on remote system\n            - password (string) : Password for remote system\n            - script_dir (string) : Full path to a script dir where\n              generated scripts could be sent to.\n            - envs (dict) : A dictionary of environment variables to be set when executing commands\n\n        Raises:\n        '''\n\n        self.hostname = hostname\n        self.username = username\n        self.password = password\n        self.kwargs = kwargs\n        self.script_dir = script_dir\n\n        self.ssh_client = paramiko.SSHClient()\n        self.ssh_client.load_system_host_keys()\n        self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())\n\n        self.envs = {}\n        if envs is not None:\n            self.envs = envs\n\n        try:\n            self.ssh_client.connect(\n                hostname,\n                username=username,\n                password=password,\n                allow_agent=True\n            )\n            t = self.ssh_client.get_transport()\n            self.sftp_client = paramiko.SFTPClient.from_transport(t)\n\n        except paramiko.BadHostKeyException as e:\n            raise BadHostKeyException(e, self.hostname)\n\n        except paramiko.AuthenticationException as e:\n            raise AuthException(e, self.hostname)\n\n        except paramiko.SSHException as e:\n            raise SSHException(e, self.hostname)\n\n        except Exception as e:\n            raise SSHException(e, self.hostname)\n\n    def prepend_envs(self, cmd, env={}):\n        env.update(self.envs)\n\n        if len(env.keys()) > 0:\n            env_vars = ' '.join(['{}={}'.format(key, value) for key, value in env.items()])\n            return 'env {0} {1}'.format(env_vars, cmd)\n        return cmd\n\n    def execute_wait(self, cmd, walltime=2, envs={}):\n        ''' Synchronously execute a commandline string on the shell.\n\n        Args:\n            - cmd (string) : Commandline string to execute\n            - walltime (int) : walltime in seconds, this is not really used now.\n\n        Kwargs:\n            - envs (dict) : Dictionary of env variables\n\n        Returns:\n            - retcode : Return code from the execution, -1 on fail\n            - stdout  : stdout string\n            - stderr  : stderr string\n\n        Raises:\n        None.\n        '''\n\n        # Execute the command\n        stdin, stdout, stderr = self.ssh_client.exec_command(\n            self.prepend_envs(cmd, envs), bufsize=-1, timeout=walltime\n        )\n        # Block on exit status from the command\n        exit_status = stdout.channel.recv_exit_status()\n        return exit_status, stdout.read().decode(\"utf-8\"), stderr.read().decode(\"utf-8\")\n\n    def execute_no_wait(self, cmd, walltime=2, envs={}):\n        ''' Execute asynchronousely without waiting for exitcode\n\n        Args:\n            - cmd (string): Commandline string to be executed on the remote side\n            - walltime (int): timeout to exec_command\n\n        KWargs:\n            - envs (dict): A dictionary of env variables\n\n        Returns:\n            - None, stdout (readable stream), stderr (readable stream)\n\n        Raises:\n            - ChannelExecFailed (reason)\n        '''\n\n        # Execute the command\n        stdin, stdout, stderr = self.ssh_client.exec_command(\n            self.prepend_envs(cmd, envs), bufsize=-1, timeout=walltime\n        )\n        # Block on exit status from the command\n        return None, stdout, stderr\n\n    def push_file(self, local_source, remote_dir):\n        ''' Transport a local file to a directory on a remote machine\n\n        Args:\n            - local_source (string): Path\n            - remote_dir (string): Remote path\n\n        Returns:\n            - str: Path to copied file on remote machine\n\n        Raises:\n            - BadScriptPath : if script path on the remote side is bad\n            - BadPermsScriptPath : You do not have perms to make the channel script dir\n            - FileCopyException : FileCopy failed.\n\n        '''\n        remote_dest = remote_dir + '/' + os.path.basename(local_source)\n\n        try:\n            self.makedirs(remote_dir, exist_ok=True)\n        except IOError as e:\n            logger.exception(\"Pushing {0} to {1} failed\".format(local_source, remote_dir))\n            if e.errno == 2:\n                raise BadScriptPath(e, self.hostname)\n            elif e.errno == 13:\n                raise BadPermsScriptPath(e, self.hostname)\n            else:\n                logger.exception(\"File push failed due to SFTP client failure\")\n                raise FileCopyException(e, self.hostname)\n        try:\n            self.sftp_client.put(local_source, remote_dest, confirm=True)\n            # Set perm because some systems require the script to be executable\n            self.sftp_client.chmod(remote_dest, 0o777)\n        except Exception as e:\n            logger.exception(\"File push from local source {} to remote destination {} failed\".format(\n                local_source, remote_dest))\n            raise FileCopyException(e, self.hostname)\n\n        return remote_dest\n\n    def pull_file(self, remote_source, local_dir):\n        ''' Transport file on the remote side to a local directory\n\n        Args:\n            - remote_source (string): remote_source\n            - local_dir (string): Local directory to copy to\n\n\n        Returns:\n            - str: Local path to file\n\n        Raises:\n            - FileExists : Name collision at local directory.\n            - FileCopyException : FileCopy failed.\n        '''\n\n        local_dest = local_dir + '/' + os.path.basename(remote_source)\n\n        try:\n            os.makedirs(local_dir)\n        except OSError as e:\n            if e.errno != errno.EEXIST:\n                logger.exception(\"Failed to create script_dir: {0}\".format(script_dir))\n                raise BadScriptPath(e, self.hostname)\n\n        # Easier to check this than to waste time trying to pull file and\n        # realize there's a problem.\n        if os.path.exists(local_dest):\n            logger.exception(\"Remote file copy will overwrite a local file:{0}\".format(local_dest))\n            raise FileExists(None, self.hostname, filename=local_dest)\n\n        try:\n            self.sftp_client.get(remote_source, local_dest)\n        except Exception as e:\n            logger.exception(\"File pull failed\")\n            raise FileCopyException(e, self.hostname)\n\n        return local_dest\n\n    def close(self):\n        return self.ssh_client.close()\n\n    def isdir(self, path):\n        \"\"\"Return true if the path refers to an existing directory.\n\n        Parameters\n        ----------\n        path : str\n            Path of directory on the remote side to check.\n        \"\"\"\n        result = True\n        try:\n            self.sftp_client.lstat(path)\n        except FileNotFoundError:\n            result = False\n\n        return result\n\n    def makedirs(self, path, mode=511, exist_ok=False):\n        \"\"\"Create a directory on the remote side.\n\n        If intermediate directories do not exist, they will be created.\n\n        Parameters\n        ----------\n        path : str\n            Path of directory on the remote side to create.\n        mode : int\n            Permissions (posix-style) for the newly-created directory.\n        exist_ok : bool\n            If False, raise an OSError if the target directory already exists.\n        \"\"\"\n        if exist_ok is False and self.isdir(path):\n            raise OSError('Target directory {} already exists'.format(path))\n\n        self.execute_wait('mkdir -p {}'.format(path))\n        self.sftp_client.chmod(path, mode)\n\n    def abspath(self, path):\n        \"\"\"Return the absolute path on the remote side.\n\n        Parameters\n        ----------\n        path : str\n            Path for which the absolute path will be returned.\n        \"\"\"\n        return self.sftp_client.normalize(path)\n\n    @property\n    def script_dir(self):\n        return self._script_dir\n\n    @script_dir.setter\n    def script_dir(self, value):\n        self._script_dir = value\n", "path": "parsl/channels/ssh/ssh.py"}], "after_files": [{"content": "import errno\nimport logging\nimport os\n\nimport paramiko\nfrom parsl.channels.base import Channel\nfrom parsl.channels.errors import *\nfrom parsl.utils import RepresentationMixin\n\nlogger = logging.getLogger(__name__)\n\n\nclass HostAuthSSHClient(paramiko.SSHClient):\n    def _auth(self, username, *args):\n        self._transport.auth_none(username)\n        return\n\n\nclass SSHChannel(Channel, RepresentationMixin):\n    ''' SSH persistent channel. This enables remote execution on sites\n    accessible via ssh. It is assumed that the user has setup host keys\n    so as to ssh to the remote host. Which goes to say that the following\n    test on the commandline should work :\n\n    >>> ssh <username>@<hostname>\n\n    '''\n\n    def __init__(self, hostname, username=None, password=None, script_dir=None, envs=None, host_auth=False, **kwargs):\n        ''' Initialize a persistent connection to the remote system.\n        We should know at this point whether ssh connectivity is possible\n\n        Args:\n            - hostname (String) : Hostname\n\n        KWargs:\n            - username (string) : Username on remote system\n            - password (string) : Password for remote system\n            - script_dir (string) : Full path to a script dir where\n              generated scripts could be sent to.\n            - envs (dict) : A dictionary of environment variables to be set when executing commands\n\n        Raises:\n        '''\n\n        self.hostname = hostname\n        self.username = username\n        self.password = password\n        self.kwargs = kwargs\n        self.script_dir = script_dir\n        self.host_auth = host_auth\n\n        if host_auth:\n            self.ssh_client = HostAuthSSHClient()\n        else:\n            self.ssh_client = paramiko.SSHClient()\n        self.ssh_client.load_system_host_keys()\n        self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())\n\n        self.envs = {}\n        if envs is not None:\n            self.envs = envs\n\n        try:\n            self.ssh_client.connect(\n                hostname,\n                username=username,\n                password=password,\n                allow_agent=True\n            )\n            t = self.ssh_client.get_transport()\n            self.sftp_client = paramiko.SFTPClient.from_transport(t)\n\n        except paramiko.BadHostKeyException as e:\n            raise BadHostKeyException(e, self.hostname)\n\n        except paramiko.AuthenticationException as e:\n            raise AuthException(e, self.hostname)\n\n        except paramiko.SSHException as e:\n            raise SSHException(e, self.hostname)\n\n        except Exception as e:\n            raise SSHException(e, self.hostname)\n\n    def prepend_envs(self, cmd, env={}):\n        env.update(self.envs)\n\n        if len(env.keys()) > 0:\n            env_vars = ' '.join(['{}={}'.format(key, value) for key, value in env.items()])\n            return 'env {0} {1}'.format(env_vars, cmd)\n        return cmd\n\n    def execute_wait(self, cmd, walltime=2, envs={}):\n        ''' Synchronously execute a commandline string on the shell.\n\n        Args:\n            - cmd (string) : Commandline string to execute\n            - walltime (int) : walltime in seconds, this is not really used now.\n\n        Kwargs:\n            - envs (dict) : Dictionary of env variables\n\n        Returns:\n            - retcode : Return code from the execution, -1 on fail\n            - stdout  : stdout string\n            - stderr  : stderr string\n\n        Raises:\n        None.\n        '''\n\n        # Execute the command\n        stdin, stdout, stderr = self.ssh_client.exec_command(\n            self.prepend_envs(cmd, envs), bufsize=-1, timeout=walltime\n        )\n        # Block on exit status from the command\n        exit_status = stdout.channel.recv_exit_status()\n        return exit_status, stdout.read().decode(\"utf-8\"), stderr.read().decode(\"utf-8\")\n\n    def execute_no_wait(self, cmd, walltime=2, envs={}):\n        ''' Execute asynchronousely without waiting for exitcode\n\n        Args:\n            - cmd (string): Commandline string to be executed on the remote side\n            - walltime (int): timeout to exec_command\n\n        KWargs:\n            - envs (dict): A dictionary of env variables\n\n        Returns:\n            - None, stdout (readable stream), stderr (readable stream)\n\n        Raises:\n            - ChannelExecFailed (reason)\n        '''\n\n        # Execute the command\n        stdin, stdout, stderr = self.ssh_client.exec_command(\n            self.prepend_envs(cmd, envs), bufsize=-1, timeout=walltime\n        )\n        # Block on exit status from the command\n        return None, stdout, stderr\n\n    def push_file(self, local_source, remote_dir):\n        ''' Transport a local file to a directory on a remote machine\n\n        Args:\n            - local_source (string): Path\n            - remote_dir (string): Remote path\n\n        Returns:\n            - str: Path to copied file on remote machine\n\n        Raises:\n            - BadScriptPath : if script path on the remote side is bad\n            - BadPermsScriptPath : You do not have perms to make the channel script dir\n            - FileCopyException : FileCopy failed.\n\n        '''\n        remote_dest = remote_dir + '/' + os.path.basename(local_source)\n\n        try:\n            self.makedirs(remote_dir, exist_ok=True)\n        except IOError as e:\n            logger.exception(\"Pushing {0} to {1} failed\".format(local_source, remote_dir))\n            if e.errno == 2:\n                raise BadScriptPath(e, self.hostname)\n            elif e.errno == 13:\n                raise BadPermsScriptPath(e, self.hostname)\n            else:\n                logger.exception(\"File push failed due to SFTP client failure\")\n                raise FileCopyException(e, self.hostname)\n        try:\n            self.sftp_client.put(local_source, remote_dest, confirm=True)\n            # Set perm because some systems require the script to be executable\n            self.sftp_client.chmod(remote_dest, 0o777)\n        except Exception as e:\n            logger.exception(\"File push from local source {} to remote destination {} failed\".format(\n                local_source, remote_dest))\n            raise FileCopyException(e, self.hostname)\n\n        return remote_dest\n\n    def pull_file(self, remote_source, local_dir):\n        ''' Transport file on the remote side to a local directory\n\n        Args:\n            - remote_source (string): remote_source\n            - local_dir (string): Local directory to copy to\n\n\n        Returns:\n            - str: Local path to file\n\n        Raises:\n            - FileExists : Name collision at local directory.\n            - FileCopyException : FileCopy failed.\n        '''\n\n        local_dest = local_dir + '/' + os.path.basename(remote_source)\n\n        try:\n            os.makedirs(local_dir)\n        except OSError as e:\n            if e.errno != errno.EEXIST:\n                logger.exception(\"Failed to create script_dir: {0}\".format(script_dir))\n                raise BadScriptPath(e, self.hostname)\n\n        # Easier to check this than to waste time trying to pull file and\n        # realize there's a problem.\n        if os.path.exists(local_dest):\n            logger.exception(\"Remote file copy will overwrite a local file:{0}\".format(local_dest))\n            raise FileExists(None, self.hostname, filename=local_dest)\n\n        try:\n            self.sftp_client.get(remote_source, local_dest)\n        except Exception as e:\n            logger.exception(\"File pull failed\")\n            raise FileCopyException(e, self.hostname)\n\n        return local_dest\n\n    def close(self):\n        return self.ssh_client.close()\n\n    def isdir(self, path):\n        \"\"\"Return true if the path refers to an existing directory.\n\n        Parameters\n        ----------\n        path : str\n            Path of directory on the remote side to check.\n        \"\"\"\n        result = True\n        try:\n            self.sftp_client.lstat(path)\n        except FileNotFoundError:\n            result = False\n\n        return result\n\n    def makedirs(self, path, mode=511, exist_ok=False):\n        \"\"\"Create a directory on the remote side.\n\n        If intermediate directories do not exist, they will be created.\n\n        Parameters\n        ----------\n        path : str\n            Path of directory on the remote side to create.\n        mode : int\n            Permissions (posix-style) for the newly-created directory.\n        exist_ok : bool\n            If False, raise an OSError if the target directory already exists.\n        \"\"\"\n        if exist_ok is False and self.isdir(path):\n            raise OSError('Target directory {} already exists'.format(path))\n\n        self.execute_wait('mkdir -p {}'.format(path))\n        self.sftp_client.chmod(path, mode)\n\n    def abspath(self, path):\n        \"\"\"Return the absolute path on the remote side.\n\n        Parameters\n        ----------\n        path : str\n            Path for which the absolute path will be returned.\n        \"\"\"\n        return self.sftp_client.normalize(path)\n\n    @property\n    def script_dir(self):\n        return self._script_dir\n\n    @script_dir.setter\n    def script_dir(self, value):\n        self._script_dir = value\n", "path": "parsl/channels/ssh/ssh.py"}]}