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
Esempio n. 3
0
    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)
Esempio n. 4
0
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]
Esempio n. 5
0
 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]
Esempio n. 6
0
File: usine.py Progetto: cbnva/usine
 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()
Esempio n. 7
0
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]
Esempio n. 9
0
 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
Esempio n. 10
0
    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]
Esempio n. 11
0
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]
Esempio n. 12
0
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)
Esempio n. 13
0
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, [])
Esempio n. 14
0
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}"
        )
Esempio n. 15
0
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)
Esempio n. 16
0
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
Esempio n. 17
0
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
Esempio n. 18
0
 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]
Esempio n. 19
0
    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)
Esempio n. 20
0
    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
Esempio n. 21
0
   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)
Esempio n. 22
0
    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)
Esempio n. 24
0
    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
Esempio n. 25
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]
Esempio n. 26
0
    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
Esempio n. 27
0
    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),
        )
Esempio n. 28
0
    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),
        )
Esempio n. 29
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]
Esempio n. 30
0
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]
Esempio n. 31
0
    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]
Esempio n. 32
0
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")
Esempio n. 33
0
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')
Esempio n. 34
0
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]
Esempio n. 35
0
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]
Esempio n. 36
0
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')
Esempio n. 37
0
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)
Esempio n. 38
0
        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)