Source code for remote_compression.ssh

from pathlib import Path
import paramiko
import time


[docs] def get_config(hostname, config_path=None): """ Parameters ---------- hostname: :class:`str` Destination config_path: :class:`str`, optional Location of the openSSH config file if different from ~/.ssh/config. Returns ------- :class:`dict` Parameters for destination Examples -------- >>> get_config('my_machine') # doctest: +NORMALIZE_WHITESPACE {'hostname': 'my_machine'} """ if config_path is None: config_path = str(Path.home() / ".ssh/config") try: config = paramiko.SSHConfig.from_path(config_path) except FileNotFoundError: config = paramiko.SSHConfig() return config.lookup(hostname)
def auto_retry(client, attempts=0, **kwargs): if attempts > 10: raise paramiko.ssh_exception.SSHException try: client.connect(**kwargs) except paramiko.ssh_exception.SSHException: time.sleep(10) auto_retry(client, attempts=attempts + 1, **kwargs)
[docs] class SSH(paramiko.SSHClient): """ Context manager for making a paramiko connection with possible proxyjump. Parameters ---------- hostname: :class:`str` Destination. `~/.ssh/config` will be used to retrieve extra parameters. Examples -------- >>> with SSH('remote_host') as ssh: # doctest: +NORMALIZE_WHITESPACE +SKIP ... _stdin, _stdout,_stderr = ssh.exec_command("pwd") ... print(_stdout.read().decode()) /home/fmathieu """ def __init__(self, hostname): self.cfg = get_config(hostname) self.gw = paramiko.SSHClient() self.ssh = paramiko.SSHClient() def __enter__(self): dest = self.cfg.get('hostname') key = self.cfg.get('identityfile') user = self.cfg.get('user') jump = self.cfg.get('proxyjump') if jump is None: sock = None else: if "@" in jump: gw_user, gw_dest = jump.split('@') else: gw_user, gw_dest = user, jump self.gw.set_missing_host_key_policy(paramiko.AutoAddPolicy()) auto_retry(self.gw, hostname=gw_dest, username=gw_user, key_filename=key, banner_timeout=100, timeout=100, auth_timeout=100, allow_agent=False) transport = self.gw.get_transport() transport.set_keepalive(60) dest_addr = (dest, 22) local_addr = ('127.0.0.1', 22) sock = transport.open_channel("direct-tcpip", dest_addr, local_addr) self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) auto_retry(self.ssh, hostname=dest, username=user, key_filename=key, sock=sock, banner_timeout=100, timeout=100, auth_timeout=100, allow_agent=False) return self.ssh def __exit__(self, exc_type, exc_val, exc_tb): self.ssh.close() self.gw.close()