def _ssh_execute(ssh, cmd, ssh_params): # NOTE(yuriyz): this ugly code is work-around against paramiko with # eventlet issues LOG.debug('Running cmd (SSH): %s', cmd) stdin_stream, stdout_stream, stderr_stream = ssh.exec_command(cmd) paramiko_channel = stdout_stream.channel paramiko_channel.setblocking(0) stdout_io = six.moves.StringIO() stderr_io = six.moves.StringIO() def _wait_execution(mutable, channel): try: stdout_data = channel.recv(1048576) except Exception: LOG.debug('No data from SSH stdout.') else: LOG.debug('Got %d from SSH stdout.', len(stdout_data)) stdout_io.write(stdout_data) try: stderr_data = channel.recv_stderr(1048576) except Exception: LOG.debug('No data from SSH stderr.') else: LOG.debug('Got %d from SSH stderr.', len(stderr_data)) stderr_io.write(stderr_data) if channel.exit_status_ready(): raise loopingcall.LoopingCallDone() try: ssh = utils.ssh_connect(ssh_params) except exception.SSHConnectFailed: mutable['error'] = True raise loopingcall.LoopingCallDone() else: ssh.close() error = {'error': False} timer = loopingcall.FixedIntervalLoopingCall(_wait_execution, error, paramiko_channel) timer.start(interval=60).wait() stdout = stdout_io.getvalue() stderr = stderr_io.getvalue() LOG.debug('SSH stdout is: "%s"', stdout) LOG.debug('SSH stderr is: "%s"', stderr) if error['error']: message = _('connection to the node lost') raise exception.SSHCommandFailed(cmd=message) exit_status = paramiko_channel.recv_exit_status() if exit_status != 0: message = _('wrong exit status %d') % exit_status raise exception.SSHCommandFailed(cmd=message) return stdout, stderr
def _ssh_execute(ssh_obj, cmd_to_exec): """Executes a command via ssh. Executes a command via ssh and returns a list of the lines of the output from the command. :param ssh_obj: paramiko.SSHClient, an active ssh connection. :param cmd_to_exec: command to execute. :returns: list of the lines of output from the command. :raises: SSHCommandFailed on an error from ssh. """ LOG.debug(_translators.log_error("Executing SSH cmd: %r"), cmd_to_exec) try: output_list = processutils.ssh_execute(ssh_obj, cmd_to_exec)[0].split('\n') except Exception as e: LOG.error( _translators.log_error( "Cannot execute SSH cmd %(cmd)s. Reason: %(err)s."), { 'cmd': cmd_to_exec, 'err': e }) raise exception.SSHCommandFailed(cmd=cmd_to_exec) return output_list