Ejemplo n.º 1
0
    def wait_finished(self, host_output, timeout=None):
        """Wait for EOF from channel and close channel.

        Used to wait for remote command completion and be able to gather
        exit code.

        :param host_output: Host output of command to wait for.
        :type host_output: :py:class:`pssh.output.HostOutput`
        :param timeout: Timeout value in seconds - defaults to no timeout.
        :type timeout: float

        :raises: :py:class:`pssh.exceptions.Timeout` after <timeout> seconds if
          timeout set.
        """
        if not isinstance(host_output, HostOutput):
            raise ValueError("%s is not a HostOutput object" % (host_output, ))
        channel = host_output.channel
        if channel is None:
            return
        logger.debug("Sending EOF on channel %s", channel)
        self._eagain(channel.send_eof, timeout=self.timeout)
        logger.debug("Waiting for readers, timeout %s", timeout)
        with GTimeout(seconds=timeout, exception=Timeout):
            joinall((host_output.buffers.stdout.reader,
                     host_output.buffers.stderr.reader))
        logger.debug("Readers finished, closing channel")
        self.close_channel(channel)
Ejemplo n.º 2
0
 def _read_output(self, read_func, timeout=None):
     remainder = b""
     remainder_len = 0
     size, data = read_func()
     t = GTimeout(seconds=timeout, exception=Timeout)
     t.start()
     try:
         while size == LIBSSH2_ERROR_EAGAIN or size > 0:
             while size == LIBSSH2_ERROR_EAGAIN:
                 self.poll(timeout=timeout)
                 size, data = read_func()
             while size > 0:
                 pos = 0
                 while pos < size:
                     linesep, new_line_pos = find_eol(data, pos)
                     if linesep == -1:
                         remainder += data[pos:]
                         remainder_len = len(remainder)
                         break
                     end_of_line = pos + linesep
                     if remainder_len > 0:
                         line = remainder + data[pos:end_of_line]
                         remainder = b""
                         remainder_len = 0
                     else:
                         line = data[pos:end_of_line]
                     yield line
                     pos += linesep + new_line_pos
                 size, data = read_func()
         if remainder_len > 0:
             # Finished reading without finding ending linesep
             yield remainder
     finally:
         t.close()
Ejemplo n.º 3
0
 def _read_output_buffer(self, _buffer, timeout=None):
     timer = GTimeout(seconds=timeout, exception=Timeout)
     remainder = b""
     remainder_len = 0
     timer.start()
     try:
         for data in _buffer:
             pos = 0
             size = len(data)
             while pos < size:
                 linesep, new_line_pos = find_eol(data, pos)
                 if linesep == -1:
                     remainder += data[pos:]
                     remainder_len = len(remainder)
                     break
                 end_of_line = pos+linesep
                 if remainder_len > 0:
                     line = remainder + data[pos:end_of_line]
                     remainder = b""
                     remainder_len = 0
                 else:
                     line = data[pos:end_of_line]
                 yield line
                 pos += linesep + new_line_pos
         if remainder_len > 0:
             # Finished reading without finding ending linesep
             yield remainder
     finally:
         timer.close()
Ejemplo n.º 4
0
 def _eagain_errcode(self, func, eagain, *args, **kwargs):
     timeout = kwargs.pop('timeout', self.timeout)
     with GTimeout(seconds=timeout, exception=Timeout):
         ret = func(*args, **kwargs)
         while ret == eagain:
             self.poll()
             ret = func(*args, **kwargs)
         return ret
Ejemplo n.º 5
0
 def _eagain(self, func, *args, **kwargs):
     timeout = kwargs.pop('timeout', self.timeout)
     with GTimeout(seconds=timeout, exception=Timeout):
         ret = func(*args, **kwargs)
         while ret == LIBSSH2_ERROR_EAGAIN:
             self.poll()
             ret = func(*args, **kwargs)
         return ret
Ejemplo n.º 6
0
 def _eagain(self, func, *args, **kwargs):
     """Run function given and handle EAGAIN for an ssh-python session"""
     timeout = kwargs.pop('timeout', self.timeout)
     with GTimeout(seconds=timeout, exception=Timeout):
         ret = func(*args, **kwargs)
         while ret == SSH_AGAIN:
             self.poll(timeout=timeout)
             ret = func(*args, **kwargs)
         return ret
    def run_command(self,
                    command,
                    sudo=False,
                    user=None,
                    use_pty=False,
                    shell=None,
                    encoding='utf-8',
                    timeout=None,
                    read_timeout=None):
        """Run remote command.

        :param command: Command to run.
        :type command: str
        :param sudo: Run command via sudo as super-user.
        :type sudo: bool
        :param user: Run command as user via sudo
        :type user: str
        :param use_pty: Whether or not to obtain a PTY on the channel.
        :type use_pty: bool
        :param shell: (Optional) Override shell to use to run command with.
          Defaults to login user's defined shell. Use the shell's command
          syntax, eg `shell='bash -c'` or `shell='zsh -c'`.
        :type shell: str
        :param encoding: Encoding to use for output. Must be valid
          `Python codec <https://docs.python.org/library/codecs.html>`_
        :type encoding: str
        :param read_timeout: (Optional) Timeout in seconds for reading output.
        :type read_timeout: float
        :param timeout: Deprecated - use read_timeout.

        :rtype: :py:class:`pssh.output.HostOutput`
        """
        # Fast path for no command substitution needed
        if not sudo and not user and not shell:
            _command = command
        else:
            _command = ''
            if sudo and not user:
                _command = 'sudo -S '
            elif user:
                _command = 'sudo -u %s -S ' % (user, )
            _shell = shell if shell else '$SHELL -c'
            _command += "%s '%s'" % (
                _shell,
                command,
            )
        _command = _command.encode(encoding)
        with GTimeout(seconds=self.timeout):
            channel = self.execute(_command, use_pty=use_pty)
        _timeout = read_timeout if read_timeout else timeout
        host_out = self._make_host_output(channel, encoding, _timeout)
        return host_out
Ejemplo n.º 8
0
 def _make_ssh_client(self, host_i, host):
     auth_thread_pool = True
     if self.proxy_host is not None and self._tunnel is None:
         self._start_tunnel_thread()
     logger.debug(
         "Make client request for host %s, (host_i, host) in clients: %s",
         host, (host_i, host) in self._host_clients)
     if (host_i, host) not in self._host_clients \
        or self._host_clients[(host_i, host)] is None:
         _user, _port, _password, _pkey = self._get_host_config_values(
             host_i, host)
         proxy_host = None if self.proxy_host is None else '127.0.0.1'
         if proxy_host is not None:
             auth_thread_pool = False
             max_wait = self.timeout if self.timeout is not None else 60
             with self._tunnel_lock:
                 self._tunnel_in_q.append((host, _port))
             with GTimeout(seconds=max_wait, exception=Timeout):
                 while True:
                     try:
                         _port = self._tunnel_out_q.pop()
                     except IndexError:
                         logger.debug(
                             "Waiting on tunnel to open listening port")
                         sleep(.1)
                     else:
                         break
         _client = SSHClient(
             host,
             user=_user,
             password=_password,
             port=_port,
             pkey=_pkey,
             num_retries=self.num_retries,
             timeout=self.timeout,
             allow_agent=self.allow_agent,
             retry_delay=self.retry_delay,
             proxy_host=proxy_host,
             _auth_thread_pool=auth_thread_pool,
             forward_ssh_agent=self.forward_ssh_agent,
             keepalive_seconds=self.keepalive_seconds,
             identity_auth=self.identity_auth,
         )
         self._host_clients[(host_i, host)] = _client
         return _client
     return self._host_clients[(host_i, host)]
Ejemplo n.º 9
0
    def test_server_start(self):
        _port = 1234

        class Server(object):
            def __init__(self):
                self.started = False
                self.listen_port = _port

        server = Server()
        forwarder = LocalForwarder()
        let = spawn(forwarder._get_server_listen_port, None, server)
        let.start()
        sleep(.01)
        server.started = True
        sleep(.01)
        with GTimeout(seconds=1):
            port = forwarder.out_q.get()
        self.assertEqual(port, _port)
Ejemplo n.º 10
0
    def wait_finished(self, channel, timeout=None):
        """Wait for EOF from channel and close channel.

        Used to wait for remote command completion and be able to gather
        exit code.

        :param channel: The channel to use.
        :type channel: :py:class:`ssh.channel.Channel`
        :param timeout: Timeout value in seconds - defaults to no timeout.
        :type timeout: float

        :raises: :py:class:`pssh.exceptions.Timeout` after <timeout> seconds if
          timeout given.
        """
        if channel is None:
            return
        logger.debug("Sending EOF on channel %s", channel)
        self._eagain(channel.send_eof, timeout=self.timeout)
        logger.debug("Waiting for readers, timeout %s", timeout)
        with GTimeout(seconds=timeout, exception=Timeout):
            joinall((self._stdout_reader, self._stderr_reader))
        logger.debug("Readers finished, closing channel")
        # Close channel
        self.close_channel(channel)