def create_worker(host): config = SSHConfig() proxy = None if os.path.exists(os.path.expanduser('~/.ssh/config')): config.parse(open(os.path.expanduser('~/.ssh/config'))) if host.hostname is not None and \ 'proxycommand' in config.lookup(host.hostname): proxy = ProxyCommand(config.lookup(host.hostname)['proxycommand']) # proxy = paramiko.ProxyCommand("ssh -o StrictHostKeyChecking=no [email protected] nc 118.138.239.241 22") worker = SSHClient() worker.load_system_host_keys() worker.set_missing_host_key_policy(AutoAddPolicy()) worker.hostname = host.hostname # store all this for later reference (e.g., logging, reconnection) worker.username = host.username worker.password = host.password worker.proxy = proxy if not host.key_filename is None: worker.pkey = RSAKey.from_private_key_file(host.key_filename, host.key_password) else: worker.pkey = None # time.sleep(4) # worker.connect(hostname=host.hostname, username=host.username, password=host.password, key_filename=host.key_filename, sock=proxy, timeout=3600) worker.connect(hostname=host.hostname, username=host.username, password=host.password, pkey=worker.pkey, sock=proxy) return worker
def create_worker(host): config = SSHConfig() proxy = None if os.path.exists(os.path.expanduser('~/.ssh/config')): with open(os.path.expanduser('~/.ssh/config')) as f: config.parse(f) if host.hostname is not None and 'proxycommand' in config.lookup( host.hostname): proxy = ProxyCommand(config.lookup(host.hostname)['proxycommand']) worker = SSHClient() worker.load_system_host_keys() worker.set_missing_host_key_policy(AutoAddPolicy()) # store data for later reference worker.host = host.hostname worker.username = host.username worker.password = host.password worker.key_filename = host.key_filename worker.connect(hostname=host.hostname, username=host.username, password=host.password, key_filename=host.key_filename, sock=proxy) return worker
def __init__(self, host): self.host = host config_file = open(expanduser('.tmp/ssh_config')) config = SSHConfig() config.parse(config_file) ip = config.lookup(host).get('hostname', None) port = config.lookup(host).get('port', 22) pk = config.lookup(host).get('identityfile', None) self.ssh = paramiko.SSHClient() self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.ssh.connect(hostname=ip, port=int(port), username=SSH_USERNAME, key_filename=pk) s = self.ssh.get_transport().open_session() paramiko.agent.AgentRequestHandler(s)
def annotate_hosts_with_ssh_config_info(): """ Load settings from ~/.ssh/config NOTE: Need to define env.hosts first. Code from http://markpasc.typepad.com/blog/2010/04/loading-ssh-config-settings-for-fabric.html """ def hostinfo(host, config): hive = config.lookup(host) if 'user' in hive: host = '%s@%s' % (hive['user'], host) if 'port' in hive: host = '%s:%s' % (host, hive['port']) return host try: config_file = file(expanduser('~/.ssh/config')) except IOError: pass else: config = SSHConfig() config.parse(config_file) keys = [config.lookup(host).get('identityfile', None) for host in env.hosts] env.key_filename = [key for key in keys if key is not None] env.hosts = [hostinfo(host, config) for host in env.hosts]
def hosts(self): """Retrieve host instances from ssh config.""" config = SSHConfig() with Path(self.user_config).open() as fileobj: config.parse(fileobj) hostnames = [i for i in config.get_hostnames() if self.is_endhost(i)] return [self.transform_to_instances(i, config.lookup(i)) for i in hostnames]
def __init__(self, hostname, configpath=None, dry_run=False): ssh_config = SSHConfig() if not hostname: print(red('"hostname" must be defined')) sys.exit(1) parsed = self.parse_host(hostname) hostname = parsed.get('hostname') username = parsed.get('username') if configpath: if not isinstance(configpath, (list, tuple)): configpath = [configpath] for path in configpath: self._load_config(path, hostname) with (Path.home() / '.ssh/config').open() as fd: ssh_config.parse(fd) ssh_config = ssh_config.lookup(hostname) self.dry_run = dry_run self.hostname = config.hostname or ssh_config['hostname'] self.username = (username or config.username or ssh_config.get('user', getuser())) self.formatter = Formatter() self.key_filenames = [] if config.key_filename: self.key_filenames.append(config.key_filename) if 'identityfile' in ssh_config: self.key_filenames.extend(ssh_config['identityfile']) self.sudo = '' self.cd = None self.screen = None self.env = {} self._sftp = None self.proxy_command = ssh_config.get('proxycommand', config.proxy_command) self.open()
def getSSHInfoForHost(host): """ Inspired by: http://markpasc.typepad.com/blog/2010/04/loading-ssh-config-settings-for-fabric.html """ from os.path import expanduser from paramiko.config import SSHConfig key = None key_filename = None host = host def hostinfo(host, config): hive = config.lookup(host) if 'hostname' in hive: host = hive['hostname'] if 'user' in hive: host = '%s@%s' % (hive['user'], host) if 'port' in hive: host = '%s:%s' % (host, hive['port']) return host try: config_file = file(expanduser('~/.ssh/config')) except IOError: pass else: config = SSHConfig() config.parse(config_file) key = config.lookup(host).get('identityfile', None) if key != None: key_filename = expanduser(key) host = hostinfo(host, config) return key_filename, host
def _annotate_hosts_with_ssh_config_info(): from os.path import expanduser from paramiko.config import SSHConfig def hostinfo(host, config): hive = config.lookup(host) if 'hostname' in hive: host = hive['hostname'] if 'user' in hive: host = '%s@%s' % (hive['user'], host) if 'port' in hive: host = '%s:%s' % (host, hive['port']) return host try: config_file = file(expanduser('~/.ssh/config')) except IOError: pass else: config = SSHConfig() config.parse(config_file) keys = [config.lookup(host).get('identityfile', None) for host in env.hosts] env.key_filename = [expanduser(key) for key in keys if key is not None] env.hosts = [hostinfo(host, config) for host in env.hosts] for role, rolehosts in env.roledefs.items(): env.roledefs[role] = [hostinfo(host, config) for host in rolehosts]
def __init__(self, hostname, configpath=None): ssh_config = SSHConfig() if not hostname: print(red('"hostname" must be defined')) sys.exit(1) parsed = self.parse_host(hostname) hostname = parsed.get('hostname') username = parsed.get('username') if configpath: if not isinstance(configpath, (list, tuple)): configpath = [configpath] for path in configpath: self._load_config(path, hostname) with (Path.home() / '.ssh/config').open() as fd: ssh_config.parse(fd) ssh_config = ssh_config.lookup(hostname) self.hostname = ssh_config['hostname'] self.username = username or ssh_config.get('user', getuser()) self.open() self.formatter = Formatter() self.sudo = '' self.cd = None self.screen = None self.env = {} self._sftp = None
def _annotate_hosts_with_ssh_config_info(): from os.path import expanduser from paramiko.config import SSHConfig def hostinfo(host, config): hive = config.lookup(host) if 'hostname' in hive: host = hive['hostname'] if 'user' in hive: host = '%s@%s' % (hive['user'], host) if 'port' in hive: host = '%s:%s' % (host, hive['port']) return host try: config_file = file(expanduser('~/.ssh/config')) except IOError: pass else: config = SSHConfig() config.parse(config_file) keys = [ config.lookup(host).get('identityfile', None) for host in env.hosts ] env.key_filename = [ expanduser(key) for key in keys if key is not None ] env.hosts = [hostinfo(host, config) for host in env.hosts]
def _annotate_hosts_with_ssh_config_info(): ''' Parse .ssh/config to get correct keys (avoids "Too many authentication failures"). env.hosts must be set. http://markpasc.typepad.com/blog/2010/04/loading-ssh-config-settings-for-fabric.html ''' from os.path import expanduser from paramiko.config import SSHConfig def hostinfo(host, config): hive = config.lookup(host) if 'hostname' in hive: host = hive['hostname'] if 'user' in hive: host = '%s@%s' % (hive['user'], host) if 'port' in hive: host = '%s:%s' % (host, hive['port']) return host try: config_file = file(expanduser('~/.ssh/config')) except IOError: pass else: config = SSHConfig() config.parse(config_file) keys = [config.lookup(host).get('identityfile', None) for host in env.hosts] env.key_filename = [expanduser(key[0]) for key in keys if key is not None] env.hosts = [hostinfo(host, config) for host in env.hosts]
def ssh_config(host): from os.path import expanduser from paramiko.config import SSHConfig def hostinfo(host, config): hive = config.lookup(host) if 'hostname' in hive: host = hive['hostname'] if 'user' in hive: host = '%s@%s' % (hive['user'], host) if 'port' in hive: host = '%s:%s' % (host, hive['port']) return host try: config_file = file(expanduser('~/.ssh/config')) except IOError: pass else: config = SSHConfig() config.parse(config_file) key = config.lookup(host).get('identityfile', None) key_filename = expanduser(key) env.key_filename = [key_filename] if key_filename else [] return hostinfo(host, config)
def _get_ssh_config(key): if not _ssh_config: ssh_config = SSHConfig() path = os.path.expanduser('~/.ssh/config') if os.path.exists(path): with open(path) as open_file: ssh_config.parse(open_file) # Create a fake hostname like "dev.myproject.ssha" to allow users to # set options in ~/.ssh/config based on the environment and project. hostname_parts = (get('config.name'), get('ssha.name'), 'ssha') hostname = '.'.join(filter(None, hostname_parts)) result = ssh_config.lookup(hostname) if 'identityfile' not in result: result['identityfile'] = [ '~/.ssh/id_rsa', '~/.ssh/id_dsa', '~/.ssh/id_ecdsa', '~/.ssh/id_ed25519', ] if 'user' not in result: user = os.environ.get('USER') if user: result['user'] = user _ssh_config.update(result) return _ssh_config.get(key, [])
def load_repo_data(): # TODO: Allow to override the current working directory, e.g. via --dir cwd = os.getcwd() repo = Repo(cwd) tracking_branch = repo.active_branch.tracking_branch() if tracking_branch: repo_branch = tracking_branch.remote_head remote_name = tracking_branch.remote_name repo_hash = tracking_branch.commit.hexsha repo_url = repo.remote(remote_name).url repo_url_parsed = giturlparse.parse(repo_url) if repo_url_parsed.protocol == "ssh": ssh_config_path = os.path.expanduser('~/.ssh/config') if os.path.exists(ssh_config_path): fp = open(ssh_config_path, 'r') config = SSHConfig() config.parse(fp) repo_url = repo_url.replace( repo_url_parsed.resource, config.lookup(repo_url_parsed.resource)['hostname']) # TODO: Detect and pass private key too fp.close() # TODO: Doesn't support unstaged changes repo_diff = repo.git.diff(repo_hash) return repo_url, repo_branch, repo_hash, repo_diff else: sys.exit( f"No tracked branch configured for branch {repo.active_branch.name}" )
def ssh_hosts(): paths = [] configs = {} try: import pwd for pw in pwd.getpwall(): config_path = path.join(pw.pw_dir, '.ssh', 'config') if path.isfile(config_path): paths.append((pw.pw_name, config_path)) except ImportError: config_path = path.expanduser(path.join('~', '.ssh', 'config')) if path.isfile(config_path): import getpass paths = [(getpass.getuser(), config_path)] for user, config_path in paths: ssh_config = SSHConfig() try: with open(config_path) as config: ssh_config.parse(config) except OSError: continue configs[user] = { host: ssh_config.lookup(host) for host in ssh_config.get_hostnames() } configs.update(ssh_putty_hosts()) return configs
def load_ssh_config(self, host): ssh_config = SSHConfig() for path in (os.path.expanduser('~/.ssh/config'), '/etc/ssh/ssh_config'): if os.path.isfile(path): with open(path) as fd: ssh_config.parse(fd) return ssh_config.lookup(host)
def from_ssh_config(cls, host, config_file=os.path.expanduser("~/.ssh/config")): if os.path.isfile(config_file): ssh_config = SSHConfig() with open(config_file) as f: ssh_config.parse(f) user_config = ssh_config.lookup(host) if 'proxycommand' in user_config: return cls(user_config['proxycommand']) return None
def __init__(self, gerrit_host_alias): ssh_config = SSHConfig() user_ssh_config_file = os.path.expanduser("~/.ssh/config") if os.path.exists(user_ssh_config_file): with open(user_ssh_config_file) as f: ssh_config.parse(f) gerrit_host_name = ssh_config.lookup(gerrit_host_alias).get("hostname") auth = HTTPBasicAuthFromNetrc("https://{}/".format(gerrit_host_alias)) self.gerrit_api_client = GerritRestAPI("https://{}/".format(gerrit_host_name), auth)
def __init__(self, hostname, user = None, filename = None): #set defaults if filename == None: filename = os.path.expanduser('~/.ssh/config') #read config file ssh_config = SSHConfig() with open(filename) as config_file: ssh_config.parse(config_file) self.update(ssh_config.lookup(hostname)) self.defaults={'port': 22, 'user': getpass.getuser(), 'hostname': hostname, 'hostkeyalias': hostname} if user != None: self['user'] = user
def __init__(self, hostname, username=None, password=None, transport=None, port=None, ssh_config_file=None): self.hostname = hostname c_args = dict() c_args['username'] = os.getenv('EOS_USER') or os.getenv( 'USER') or username c_args['password'] = os.getenv('EOS_PASSWORD') or os.getenv( 'PASSWORD') or password if port: c_args['port'] = port ssh_config_file = ssh_config_file or os.getenv('EOS_SSH_CONFIG') if ssh_config_file: ssh_config = SSHConfig() ssh_config.parse(open(ssh_config_file)) found = ssh_config.lookup(hostname) if 'user' in found: c_args['username'] = found['user'] if 'hostname' in found: c_args['host'] = found['hostname'] if 'localforward' in found: port = int(first(found['localforward']).split()[0]) c_args['port'] = port c_args['host'] = 'localhost' else: c_args['host'] = hostname c_args['transport'] = transport or self.DEFAULT_TRANSPORT self.api = pyeapi.connect(**c_args)
def __init__(self, hostname, user=None, filename=None): #set defaults if filename == None: filename = os.path.expanduser('~/.ssh/config') #read config file ssh_config = SSHConfig() with open(filename) as config_file: ssh_config.parse(config_file) self.update(ssh_config.lookup(hostname)) self.defaults = { 'port': 22, 'user': getpass.getuser(), 'hostname': hostname, 'hostkeyalias': hostname } if user != None: self['user'] = user
def annotate_from_sshconfig(env): """ Adds support for reading the host names, users and ports from ~/ssh/config Replaces the hosts defined in ssh config with actual host names, so that Fabric can take the advantage from it .. IMPORTANT:: This does not support /etc/ssh/ssh_config yet! """ from os.path import expanduser from paramiko.config import SSHConfig def hostinfo(host, config): hive = config.lookup(host) if 'hostname' in hive: host = hive['hostname'] if 'user' in hive: host = '%s@%s' % (hive['user'], host) if 'port' in hive: host = '%s:%s' % (host, hive['port']) return host # Look for user config, if found, parse it and update roledefs. Otherwise just ignore it (it is not required at all) try: config_file = file(expanduser('~/.ssh/config')) except IOError: pass else: config = SSHConfig() config.parse(config_file) keys = [ config.lookup(host).get('identityfile', None) for host in api.env.hosts ] env.key_filename = [expanduser(key) for key in keys if key is not None] env.hosts = [hostinfo(host, config) for host in env.hosts] for role, rolehosts in env.roledefs.items(): env.roledefs[role] = [hostinfo(host, config) for host in rolehosts]
def __init__(self, hostname: str, root: Path, port: int, username: str, password: str, key: Union[PathLike, Sequence[PathLike]]): ssh = SSHClient() ssh.load_system_host_keys() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) config_path = Path('~/.ssh/config').expanduser() if config_path.exists(): with open(config_path) as f: config = SSHConfig() config.parse(f) host = config.lookup(hostname) hostname = host.get('hostname', hostname) port = host.get('port', port) username = host.get('user', username) key = host.get('identityfile', key) [self.hostname, self.port, self.username, self.password, self.key] = hostname, port, username, password, key self.root = root self.ssh = ssh
def open_gateway(self): """ Obtain a socket-like object from `gateway`. :returns: A ``direct-tcpip`` `paramiko.channel.Channel`, if `gateway` was a `.Connection`; or a `~paramiko.proxy.ProxyCommand`, if `gateway` was a string. .. versionadded:: 2.0 """ # ProxyCommand is faster to set up, so do it first. if isinstance(self.gateway, string_types): # Leverage a dummy SSHConfig to ensure %h/%p/etc are parsed. # TODO: use real SSH config once loading one properly is # implemented. ssh_conf = SSHConfig() dummy = "Host {}\n ProxyCommand {}" ssh_conf.parse(StringIO(dummy.format(self.host, self.gateway))) return ProxyCommand(ssh_conf.lookup(self.host)["proxycommand"]) # Handle inner-Connection gateway type here. # TODO: logging self.gateway.open() # TODO: expose the opened channel itself as an attribute? (another # possible argument for separating the two gateway types...) e.g. if # someone wanted to piggyback on it for other same-interpreter socket # needs... # TODO: and the inverse? allow users to supply their own socket/like # object they got via $WHEREEVER? # TODO: how best to expose timeout param? reuse general connection # timeout from config? return self.gateway.transport.open_channel( kind="direct-tcpip", dest_addr=(self.host, int(self.port)), # NOTE: src_addr needs to be 'empty but not None' values to # correctly encode into a network message. Theoretically Paramiko # could auto-interpret None sometime & save us the trouble. src_addr=("", 0), )
def annotate_from_sshconfig(env): """ Adds support for reading the host names, users and ports from ~/ssh/config Replaces the hosts defined in ssh config with actual host names, so that Fabric can take the advantage from it .. IMPORTANT:: This does not support /etc/ssh/ssh_config yet! """ from os.path import expanduser from paramiko.config import SSHConfig def hostinfo(host, config): hive = config.lookup(host) if "hostname" in hive: host = hive["hostname"] if "user" in hive: host = "%s@%s" % (hive["user"], host) if "port" in hive: host = "%s:%s" % (host, hive["port"]) return host # Look for user config, if found, parse it and update roledefs. Otherwise just ignore it (it is not required at all) try: config_file = file(expanduser("~/.ssh/config")) except IOError: pass else: config = SSHConfig() config.parse(config_file) keys = [config.lookup(host).get("identityfile", None) for host in api.env.hosts] env.key_filename = [expanduser(key) for key in keys if key is not None] env.hosts = [hostinfo(host, config) for host in env.hosts] for role, rolehosts in env.roledefs.items(): env.roledefs[role] = [hostinfo(host, config) for host in rolehosts]
def _annotate_hosts_with_ssh_config_info(path): from os.path import expanduser from paramiko.config import SSHConfig def hostinfo(host, config): hive = config.lookup(host) # if 'hostname' in hive: # host = hive['hostname'] if 'user' in hive: host = '%s@%s' % (hive['user'], host) if 'port' in hive: host = '%s:%s' % (host, hive['port']) #print 'hive',hive #print 'host',host return host try: config_file = file(expanduser(path)) except IOError: pass else: config = SSHConfig() config.parse(config_file) # add hosts from ssh config to env.host & sort + unique env.hosts.extend([h for h in config.get_hostnames() if len(h) > 1]) env.hosts = sorted(set(env.hosts)) keys = [config.lookup(host).get('identityfile', None) for host in env.hosts] # flatten keys = [item for sublist in keys if sublist is not None for item in sublist] env.key_filename = [expanduser(key) for key in keys if key is not None] env.hosts = [hostinfo(host, config) for host in env.hosts] for role, rolehosts in env.roledefs.items(): env.roledefs[role] = [hostinfo(host, config) for host in rolehosts]
def _annotate_hosts_with_ssh_config_info(): from os.path import expanduser from paramiko.config import SSHConfig def hostinfo(host, config): hive = config.lookup(host) if "hostname" in hive: host = hive["hostname"] if "user" in hive: host = "%s@%s" % (hive["user"], host) if "port" in hive: host = "%s:%s" % (host, hive["port"]) return host try: config_file = file(expanduser("~/.ssh/config")) except IOError: pass else: config = SSHConfig() config.parse(config_file) keys = [config.lookup(host).get("identityfile", None) for host in env.hosts] env.key_filename = [expanduser(key) for key in keys if key is not None] env.hosts = [hostinfo(host, config) for host in env.hosts]
class SystemVM(object): def __init__(self, host="default", vagrantDir=None, controlVagrant=True): global _defaultVagrantDir self.host = host self._controlVagrant = controlVagrant if vagrantDir is None: vagrantDir = _defaultVagrantDir self._vagrant = Vagrant(root=vagrantDir) self._startedVagrant = False self._sshClient = None self._sshConfigStr = None self._sshConfig = None self._sshHostConfig = None def maybeUp(self): if not self._controlVagrant: return state = self._vagrant.status(vm_name=self.host)[0].state if state == Vagrant.NOT_CREATED: self._vagrant.up(vm_name=self.host) self._startedVagrant = True elif state in [Vagrant.POWEROFF, Vagrant.SAVED, Vagrant.ABORTED]: raise Exception("SystemVM testing does not support resume(), do not use vagrant suspend/halt") elif state == Vagrant.RUNNING: self._startedVagrant = False else: raise Exception("Unrecognized vagrant state %s" % state) def maybeDestroy(self): if not self._controlVagrant or not self._startedVagrant: return self._vagrant.destroy(vm_name=self.host) if self._sshClient is not None: self._sshClient.close() def loadSshConfig(self): if self._sshConfig is None: self._sshConfigStr = self._vagrant.ssh_config(vm_name=self.host) configObj = StringIO(self._sshConfigStr) self._sshConfig = SSHConfig() # noinspection PyTypeChecker self._sshConfig.parse(configObj) self._sshHostConfig = self._sshConfig.lookup(self.host) @property def sshConfig(self): if self._sshConfig is None: self.loadSshConfig() return self._sshConfig @property def sshConfigStr(self): if self._sshConfigStr is None: self.loadSshConfig() return self._sshConfigStr @property def sshClient(self): if self._sshClient is None: self.loadSshConfig() self._sshClient = SSHClient() self._sshClient.set_missing_host_key_policy(AutoAddPolicy()) self._sshClient.connect(self.hostname, self.sshPort, self.sshUser, key_filename=self.sshKey, timeout=10) return self._sshClient @property def hostname(self): return self._sshHostConfig.get("hostname", self.host) @property def sshPort(self): return int(self._sshHostConfig.get("port", 22)) @property def sshUser(self): return self._sshHostConfig.get("user", "root") @property def sshKey(self): return self._sshHostConfig.get("identityfile", "~/.ssh/id_rsa")
class WorkerInterface(object): """An interface to perform tasks on the DAQ worker nodes. This is used perform tasks on the computers running the data router and the ECC server. This includes things like cleaning up the data files at the end of each run. The connection is made using SSH, and the SSH config file at ``config_path`` is honored in making the connection. Additionally, the server *must* accept connections authenticated using a public key, and this public key must be available in your ``.ssh`` directory. Parameters ---------- hostname : str The hostname to connect to. port : int, optional The port that the SSH server is listening on. The default is 22. username : str, optional The username to use. If it isn't provided, a username will be read from the SSH config file. If no username is listed there, the name of the user running the code will be used. config_path : str, optional The path to the SSH config file. The default is ``~/.ssh/config``. """ def __init__(self, hostname, port=22, username=None, config_path=None): self.hostname = hostname self.client = SSHClient() self.client.load_system_host_keys() self.client.set_missing_host_key_policy(AutoAddPolicy()) if config_path is None: config_path = os.path.join(os.path.expanduser('~'), '.ssh', 'config') self.config = SSHConfig() with open(config_path) as config_file: self.config.parse(config_file) if hostname in self.config.get_hostnames(): host_cfg = self.config.lookup(hostname) full_hostname = host_cfg.get('hostname', hostname) if username is None: username = host_cfg.get('user', None) # If none, it will try the user running the server. else: full_hostname = hostname self.client.connect(full_hostname, port, username=username) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.client.close() def find_data_router(self): """Find the working directory of the data router process. The directory is found using ``lsof``, which must be available on the remote system. Returns ------- str The directory where the data router is running, and therefore writing data. Raises ------ RuntimeError If ``lsof`` finds something strange instead of a process called ``dataRouter``. """ stdin, stdout, stderr = self.client.exec_command('lsof -a -d cwd -c dataRouter -Fcn') for line in stdout: if line[0] == 'c' and not re.match('cdataRouter', line): raise RuntimeError("lsof found {} instead of dataRouter".format(line[1:].strip())) elif line[0] == 'n': return line[1:].strip() else: raise RuntimeError("lsof didn't find dataRouter") def get_graw_list(self): """Get a list of GRAW files in the data router's working directory. Returns ------- list[str] A list of the full paths to the GRAW files. """ data_dir = self.find_data_router() with self.client.open_sftp() as sftp: full_list = sftp.listdir(data_dir) graws = filter(lambda s: re.match(r'.*\.graw$', s), full_list) full_graw_paths = (os.path.join(data_dir, filename) for filename in graws) return list(full_graw_paths) def working_dir_is_clean(self): """Check if there are GRAW files in the data router's working directory. Returns ------- bool True if there are files in the working directory, False otherwise. """ return len(self.get_graw_list()) == 0 def _check_process_status(self, process_name): """Checks if the given process is running. Parameters ---------- process_name : str The name of the process to look for Returns ------- bool True if the process is running. """ _, stdout, _ = self.client.exec_command('ps -e') for line in stdout: if re.search(process_name, line): return True else: return False def check_ecc_server_status(self): """Checks if the ECC server is running. Returns ------- bool True if ``getEccSoapServer`` is running. """ return self._check_process_status(r'getEccSoapServer') def check_data_router_status(self): """Checks if the data router is running. Returns ------- bool True if ``dataRouter`` is running. """ return self._check_process_status(r'dataRouter') def build_run_dir_path(self, experiment_name, run_number): """Get the path to the directory for a given run. This returns a path of the format ``experiment_name/run_name`` under the directory where the data router is running. The ``run_name``, in this case, has the format ``run_NNNN``. Parameters ---------- experiment_name : str The name of the experiment directory. run_number : int The run number. Returns ------- run_dir : str The full path to the run directory. *This should be escaped before passing it to a shell command.* """ pwd = self.find_data_router() run_name = 'run_{:04d}'.format(run_number) # run_0001, run_0002, etc. run_dir = os.path.join(pwd, experiment_name, run_name) return run_dir def organize_files(self, experiment_name, run_number): """Organize the GRAW files at the end of a run. This will get a list of the files written in the working directory of the data router and move them to the directory ``./experiment_name/run_name``, which will be created if necessary. For example, if the ``experiment_name`` is "test" and the ``run_number`` is 4, the files will be placed in ``./test/run_0004``. Parameters ---------- experiment_name : str A name for the experiment directory. run_number : int The current run number. """ run_dir = self.build_run_dir_path(experiment_name, run_number) graws = self.get_graw_list() with self.client.open_sftp() as sftp: mkdir_recursive(sftp, run_dir) for srcpath in graws: _, srcfile = os.path.split(srcpath) destpath = os.path.join(run_dir, srcfile) sftp.rename(srcpath, destpath) def backup_config_files(self, experiment_name, run_number, file_paths, backup_root): """Makes a copy of the config files on the remote computer. The files are copied to a subdirectory ``experiment_name/run_name`` of ``backup_root``. Parameters ---------- experiment_name : str The name of the experiment. run_number : int The run number. file_paths : iterable of str The *full* paths to the config files. backup_root : str Where the backups should be written. """ run_name = 'run_{:04d}'.format(run_number) backup_dest = os.path.join(backup_root, experiment_name, run_name) with self.client.open_sftp() as sftp: mkdir_recursive(sftp, backup_dest) for source_path in file_paths: dest_path = os.path.join(backup_dest, os.path.basename(source_path)) with sftp.open(source_path, 'r') as src, sftp.open(dest_path, 'w') as dest: buffer = src.read() dest.write(buffer) def tail_file(self, path, num_lines=50): """Retrieve the tail of a text file on the remote host. Note that this assumes the file is ASCII-encoded plain text. Parameters ---------- path : str Path to the file. num_lines : int The number of lines to include. Returns ------- str The tail of the file's contents. """ # Based on https://gist.github.com/volker48/3437288 with self.client.open_sftp() as sftp: with sftp.open(path, 'r') as f: f.seek(-1, SFTPFile.SEEK_END) lines = 0 while lines < num_lines and f.tell() > 0: char = f.read(1) if char == b'\n': lines += 1 if lines == num_lines: break f.seek(-2, SFTPFile.SEEK_CUR) return f.read().decode('ascii')
class SshClient(object): def __init__(self, containers_file, extra_ssh_config_file): with open(conf.containers_file()) as infile: containers = yaml.load(infile) self._containers = [] self._container_default_config = {} self._ssh_config = SSHConfig() if extra_ssh_config_file is not None: with open(extra_ssh_config_file) as ssh_config_file: self._ssh_config.parse(ssh_config_file) self._missing_host_key_policy = AutoAddPolicy() for container_config in containers: if container_config['Host'] == '*': self._container_default_config = container_config break for container_config in containers: if container_config['Host'] == '*': continue container_host = container_config['Host'] ip_address = self._get_hostname_option(container_config) container = { 'Hostname': container_host, 'Id': container_host, 'Name': container_host, 'Labels': { 'interface': container_config['Interface'], 'type': container_config['Type'] }, 'State': { 'Running': 'running' }, 'NetworkSettings': { 'IPAddress': ip_address, 'MacAddress': None, 'Ports': None }, 'Config': container_config } self._containers.append(container) self.next_exec_id = 0 self.ssh_connections = {} self.execs = {} def inspect_container(self, container_id): for container in self._containers: if container_id == container['Id']: return { 'Name': container['Name'], 'Config': container, 'State': container['State'], 'NetworkSettings': container['NetworkSettings'] } return None def containers(self, all=None): return self._containers def get_container_by_name(self, container_name): for container in self._containers: if container_name == str(container['Name']).translate(None, '/'): return container return None def exec_create(self, container_name, cmd, stdout=True, stderr=True, tty=False): LOG.info("Running command %s at container %s " % (cmd, container_name)) exec_id = self.next_exec_id self.next_exec_id += 1 self.execs[exec_id] = (container_name, cmd, None, None) return exec_id def exec_start(self, exec_id, detach=False, stream=False): container_name, cmd, stdout, stderr = self.execs[exec_id] ssh_connection = self._get_ssh_connection(container_name) stdin, stdout, stderr = ssh_connection.exec_command(cmd) if stream: self.execs[exec_id] = (container_name, cmd, stdout, stderr) return stdout else: return ''.join(stdout.readlines()) def exec_inspect(self, exec_id, detach=False, stream=False): container_name, cmd, stdout, stderr = self.execs[exec_id] if stdout.channel.exit_status_ready(): running = False exit_code = stdout.channel.recv_exit_status() else: running = True exit_code = "N/A" return { 'Running': running, 'ProcessConfig': { 'entrypoint': cmd.split(' ')[0], 'arguments': cmd.split(' ')[1:] }, 'ExitCode': exit_code } def _get_option(self, container_config, option, paramiko_option, default): return container_config.get( option, self._container_default_config.get( option, self._ssh_config.lookup(container_config['Host']).get( paramiko_option, default))) def _get_hostname_option(self, container_config): hostname = self._get_option(container_config, 'HostName', 'hostname', 'localhost') return socket.gethostbyname(hostname) def _get_port_option(self, container_config): return int(self._get_option(container_config, 'Port', 'port', '22')) def _get_user_option(self, container_config): return self._get_option(container_config, 'User', 'user', 'root') def _get_password_option(self, container_config): return self._get_option(container_config, 'Password', 'password', None) def _get_identity_file_option(self, container_config): return self._get_option(container_config, 'IdentityFile', 'identityfile', '/dev/null') def _get_strict_host_key_checking_option(self, container_config): return self._get_option(container_config, 'StrictHostKeyChecking', 'stricthostkeychecking', 'yes') def _get_user_known_hosts_file(self, container_config): return self._get_option(container_config, 'UserKnownHostsFile', 'userknownhostsfile', '/dev/null') def _get_ssh_connection(self, container_name): if container_name in self.ssh_connections: return self.ssh_connections[container_name] config = self.get_container_by_name(container_name)['Config'] ssh_connection = paramiko.SSHClient() ssh_connection.load_system_host_keys() ssh_connection.set_missing_host_key_policy( self._missing_host_key_policy) try: ssh_connection.connect( self._get_hostname_option(config), port=self._get_port_option(config), username=self._get_user_option(config), password=self._get_password_option(config), key_filename=self._get_identity_file_option(config), look_for_keys=False, allow_agent=False) except paramiko.ssh_exception.AuthenticationException: raise Exception("AuthenticationException while trying to " + ("connect to %s container: %s with config %s" % (container_name, container_name, config))) self.ssh_connections[container_name] = ssh_connection return self.ssh_connections[container_name]
class SshClient(object): def __init__(self, containers_file, extra_ssh_config_file): with open(conf.containers_file()) as infile: containers = yaml.load(infile) self._containers = [] self._container_default_config = {} self._ssh_config = SSHConfig() if extra_ssh_config_file is not None: with open(extra_ssh_config_file) as ssh_config_file: self._ssh_config.parse(ssh_config_file) self._missing_host_key_policy = AutoAddPolicy() for container_config in containers: if container_config['Host'] == '*': self._container_default_config = container_config break for container_config in containers: if container_config['Host'] == '*': continue container_host = container_config['Host'] ip_address = self._get_hostname_option(container_config) container = { 'Hostname': container_host, 'Id': container_host, 'Name': container_host, 'Labels': { 'interface': container_config['Interface'], 'type': container_config['Type'] }, 'State': { 'Running': 'running' }, 'NetworkSettings': { 'IPAddress': ip_address, 'MacAddress': None, 'Ports': None }, 'Config': container_config } self._containers.append(container) self.next_exec_id = 0 self.ssh_connections = {} self.execs = {} def inspect_container(self, container_id): for container in self._containers: if container_id == container['Id']: return {'Name': container['Name'], 'Config': container, 'State': container['State'], 'NetworkSettings': container['NetworkSettings']} return None def containers(self, all=None): return self._containers def get_container_by_name(self, container_name): for container in self._containers: if container_name == str(container['Name']).translate(None, '/'): return container return None def exec_create(self, container_name, cmd, stdout=True, stderr=True, tty=False): LOG.info("Running command %s at container %s " % (cmd, container_name)) exec_id = self.next_exec_id self.next_exec_id += 1 self.execs[exec_id] = (container_name, cmd, None, None) return exec_id def exec_start(self, exec_id, detach=False, stream=False): container_name, cmd, stdout, stderr = self.execs[exec_id] ssh_connection = self._get_ssh_connection(container_name) stdin, stdout, stderr = ssh_connection.exec_command(cmd) if stream: self.execs[exec_id] = (container_name, cmd, stdout, stderr) return stdout else: return ''.join(stdout.readlines()) def exec_inspect(self, exec_id, detach=False, stream=False): container_name, cmd, stdout, stderr = self.execs[exec_id] if stdout.channel.exit_status_ready(): running = False exit_code = stdout.channel.recv_exit_status() else: running = True exit_code = "N/A" return {'Running': running, 'ProcessConfig': { 'entrypoint': cmd.split(' ')[0], 'arguments': cmd.split(' ')[1:]}, 'ExitCode': exit_code} def _get_option(self, container_config, option, paramiko_option, default): return container_config.get(option, self._container_default_config.get(option, self._ssh_config.lookup(container_config['Host']).get(paramiko_option, default))) def _get_hostname_option(self, container_config): hostname = self._get_option(container_config, 'HostName', 'hostname', 'localhost') return socket.gethostbyname(hostname) def _get_port_option(self, container_config): return int(self._get_option(container_config, 'Port', 'port', '22')) def _get_user_option(self, container_config): return self._get_option(container_config, 'User', 'user', 'root') def _get_password_option(self, container_config): return self._get_option(container_config, 'Password', 'password', None) def _get_identity_file_option(self, container_config): return self._get_option(container_config, 'IdentityFile', 'identityfile', '/dev/null') def _get_strict_host_key_checking_option(self, container_config): return self._get_option(container_config, 'StrictHostKeyChecking', 'stricthostkeychecking', 'yes') def _get_user_known_hosts_file(self, container_config): return self._get_option(container_config, 'UserKnownHostsFile', 'userknownhostsfile', '/dev/null') def _get_ssh_connection(self, container_name): if container_name in self.ssh_connections: return self.ssh_connections[container_name] config = self.get_container_by_name(container_name)['Config'] ssh_connection = paramiko.SSHClient() ssh_connection.load_system_host_keys() ssh_connection.set_missing_host_key_policy(self._missing_host_key_policy) try: ssh_connection.connect(self._get_hostname_option(config), port=self._get_port_option(config), username=self._get_user_option(config), password=self._get_password_option(config), key_filename=self._get_identity_file_option(config), look_for_keys=False, allow_agent=False ) except paramiko.ssh_exception.AuthenticationException: raise Exception("AuthenticationException while trying to " + ("connect to %s container: %s with config %s" % (container_name, container_name, config))) self.ssh_connections[container_name] = ssh_connection return self.ssh_connections[container_name]
class SystemVM(object): def __init__(self, host='default', vagrantDir=None, controlVagrant=True): global _defaultVagrantDir self.host = host self._controlVagrant = controlVagrant if vagrantDir is None: vagrantDir = _defaultVagrantDir self._vagrant = Vagrant(root=vagrantDir) self._startedVagrant = False self._sshClient = None self._sshConfigStr = None self._sshConfig = None self._sshHostConfig = None def maybeUp(self): if not self._controlVagrant: return state = self._vagrant.status(vm_name=self.host)[0].state if state == Vagrant.NOT_CREATED: self._vagrant.up(vm_name=self.host) self._startedVagrant = True elif state in [Vagrant.POWEROFF, Vagrant.SAVED, Vagrant.ABORTED]: raise Exception( "SystemVM testing does not support resume(), do not use vagrant suspend/halt" ) elif state == Vagrant.RUNNING: self._startedVagrant = False else: raise Exception("Unrecognized vagrant state %s" % state) def maybeDestroy(self): if not self._controlVagrant or not self._startedVagrant: return self._vagrant.destroy(vm_name=self.host) if self._sshClient is not None: self._sshClient.close() def loadSshConfig(self): if self._sshConfig is None: self._sshConfigStr = self._vagrant.ssh_config(vm_name=self.host) configObj = StringIO(self._sshConfigStr) self._sshConfig = SSHConfig() # noinspection PyTypeChecker self._sshConfig.parse(configObj) self._sshHostConfig = self._sshConfig.lookup(self.host) @property def sshConfig(self): if self._sshConfig is None: self.loadSshConfig() return self._sshConfig @property def sshConfigStr(self): if self._sshConfigStr is None: self.loadSshConfig() return self._sshConfigStr @property def sshClient(self): if self._sshClient is None: self.loadSshConfig() self._sshClient = SSHClient() self._sshClient.set_missing_host_key_policy(AutoAddPolicy()) self._sshClient.connect(self.hostname, self.sshPort, self.sshUser, key_filename=self.sshKey, timeout=10) return self._sshClient @property def hostname(self): return self._sshHostConfig.get('hostname', self.host) @property def sshPort(self): return int(self._sshHostConfig.get('port', 22)) @property def sshUser(self): return self._sshHostConfig.get('user', 'root') @property def sshKey(self): return self._sshHostConfig.get('identityfile', '~/.ssh/id_rsa')
class RemoteHost: PATH_CONFIG = '~/.ssh/config' def __init__(self, host, credential=None, stdout_queue=None, stderr_queue=None): self._password = None self.host = host self.credential = credential self.stdout_queue = stdout_queue self.stderr_queue = stderr_queue self.client = SSHClient() self.client.set_missing_host_key_policy(AutoAddPolicy()) self.config = SSHConfig() self.forward_agent = False self.parse_config_if_exists() def __enter__(self): self.client.load_system_host_keys() self.connect() return self def __exit__(self, exc_type, exc_value, traceback): self.disconnect() def parse_config_if_exists(self): path = os.path.expanduser(self.PATH_CONFIG) if os.path.exists(path): with open(path) as f: self.config.parse(f) def connect(self): host_config = self.config.lookup(self.host) log.debug('ssh-config: %s' % host_config) forwardagent = host_config.get('forwardagent') if forwardagent is not None and forwardagent == 'yes': self.forward_agent = True log.debug('forwarding agent is enabled') param = { 'sock': None, 'timeout': 10.0, } proxy_command = host_config.get('proxycommand') if proxy_command is not None: param['sock'] = ProxyCommand(proxy_command) if self.credential is not None: param.update(self.credential.connect_param) self.client.connect(self.host, **param) log.info('connected: %s' % self.host) def disconnect(self): self.client.close() @property def password(self): if self._password is None: self._password = getpass('Password: '******'ascii') + b'\n' return self._password @password.setter def password(self, value): self._password = value def is_active(self): transport = self.client.get_transport() return transport is not None and transport.is_active() async def run_async(self, command, stdin_param=None, get_pty=False, interval=10, callback=None, buff_size=1024): if not self.is_active(): log.error('ssh connection is not active') return transport = self.client.get_transport() channel = transport.open_session() if self.forward_agent: AgentRequestHandler(channel) if get_pty: channel.get_pty() channel.set_combine_stderr(True) channel.exec_command(command.encode(sys.stdout.encoding)) if stdin_param is not None: stdin = channel.makefile('wb', -1) stdin.write(stdin_param) stdin.flush() while not channel.exit_status_ready(): if callback is not None: callback(channel) await asyncio.sleep(interval) if channel.exit_status != 0: log.warn('%s exit status is not zero: %d' % (self.host, channel.exit_status)) stdout = stderr = b'' while channel.recv_ready(): stdout += channel.recv(buff_size) await asyncio.sleep(1) if stdout and self.stdout_queue is not None: s = stdout.decode(sys.stdout.encoding) self.stdout_queue.put_nowait(s) while channel.recv_stderr_ready(): stderr += channel.recv_stderr(buff_size) await asyncio.sleep(1) if stderr and self.stderr_queue is not None: s = stderr.decode(sys.stderr.encoding) self.stderr_queue.put_nowait(s) return channel.exit_status, stdout, stderr async def sudo_async(self, command, password=None, **kwargs): cmd = 'sudo %s' % command if password is not None: self.password = password return await self.run_async(cmd, stdin_param=self.password, get_pty=True, **kwargs) def run(self, command, stdin_param=None, combine_stderr=False, **kwargs): if not self.is_active(): log.error('ssh connection is not active') return cmd = command.encode(sys.stdout.encoding) stdin, stdout, stderr = self.client.exec_command(cmd, **kwargs) if stdin_param is not None: stdin.write(stdin_param) stdin.flush() stdout.channel.set_combine_stderr(combine_stderr) out = stdout.read().decode(sys.stdout.encoding) if out: log.info('%s stdout:\n%s' % (self.host, out.strip())) status_code = stdout.channel.recv_exit_status() if status_code != 0: err = stderr.read().decode(sys.stdout.encoding) if err: log.warn('%s stderr:\n%s' % (self.host, err.strip())) return status_code def sudo(self, command): cmd = 'sudo %s' % command return self.run(cmd, stdin_param=self.password, get_pty=True)
error("Can't guess CR ID and it's not specified") verbose("Using CR ID '%s'" % crId) # ** Setup paramico ** # paramiko.common.logging.basicConfig(level=paramiko.common.DEBUG) # paramiko.util.log_to_file('/tmp/sftp_webrev.log') verbose("Using hostname '%s'" % _hostname) # get username from ssh config or current user if it's not set in command line if _username == None: ssh_config = SSHConfig() try: with open(os.path.expanduser(_sshconfig_file)) as fh: ssh_config.parse(fh) hostdata = ssh_config.lookup(_hostname) _username = hostdata["user"] except Exception as e: verbose("Can't extract username from ssh config file %s" % repr(e)) if _username == None: _username = getpass.getuser() verbose("Using username '%s'" % _username) hostkey_file = os.path.expanduser(_hostkeys_file) verbose("Using hostkey file '%s'" % hostkey_file) try: host_keys = paramiko.util.load_host_keys(hostkey_file) except IOError: error("Unable to open host keys file '%s'" % hostkey_file)