X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2Fssh.py;h=1908da41539b5e8ac0b06985f1b2dc9bd8e321d4;hb=a6d233d80c359813cc0a350f07449c03d552d166;hp=e89daf291528e45825aafcf65846e8a8b8f49614;hpb=72ae46cda69c2f12efdbe731e37dce200a48f424;p=csit.git diff --git a/resources/libraries/python/ssh.py b/resources/libraries/python/ssh.py index e89daf2915..1908da4153 100644 --- a/resources/libraries/python/ssh.py +++ b/resources/libraries/python/ssh.py @@ -16,7 +16,6 @@ import socket import StringIO - from time import time, sleep from paramiko import RSAKey, SSHClient, AutoAddPolicy @@ -24,6 +23,8 @@ from paramiko.ssh_exception import SSHException, NoValidConnectionsError from robot.api import logger from scp import SCPClient, SCPException +from resources.libraries.python.OptionString import OptionString +from resources.libraries.python.PythonThree import raise_from __all__ = ["exec_cmd", "exec_cmd_no_error"] @@ -103,13 +104,13 @@ class SSH(object): peer=self._ssh.get_transport().getpeername(), total=(time() - start), ssh=self._ssh)) - except SSHException: - raise IOError('Cannot connect to {host}'. - format(host=node['host'])) + except SSHException as exc: + raise_from(IOError('Cannot connect to {host}'.format( + host=node['host'])), exc) except NoValidConnectionsError as err: - logger.error(repr(err)) - raise IOError('Unable to connect to port {port} on {host}'. - format(port=node['port'], host=node['host'])) + raise_from(IOError( + 'Unable to connect to port {port} on {host}'.format( + port=node['port'], host=node['host'])), err) def disconnect(self, node=None): """Close SSH connection to the node. @@ -156,17 +157,15 @@ class SSH(object): :rtype: tuple(int, str, str) :raises SSHTimeout: If command is not finished in timeout time. """ + if isinstance(cmd, (list, tuple)): + cmd = OptionString(cmd) cmd = str(cmd) stdout = StringIO.StringIO() stderr = StringIO.StringIO() try: chan = self._ssh.get_transport().open_session(timeout=5) peer = self._ssh.get_transport().getpeername() - except AttributeError: - self._reconnect() - chan = self._ssh.get_transport().open_session(timeout=5) - peer = self._ssh.get_transport().getpeername() - except SSHException: + except (AttributeError, SSHException): self._reconnect() chan = self._ssh.get_transport().open_session(timeout=5) peer = self._ssh.get_transport().getpeername() @@ -239,10 +238,12 @@ class SSH(object): >>> # Execute command with input (sudo -S cmd <<< "input") >>> ssh.exec_command_sudo("vpp_api_test", "dump_interface_table") """ + if isinstance(cmd, (list, tuple)): + cmd = OptionString(cmd) if cmd_input is None: - command = 'sudo -S {c}'.format(c=cmd) + command = 'sudo -E -S {c}'.format(c=cmd) else: - command = 'sudo -S {c} <<< "{i}"'.format(c=cmd, i=cmd_input) + command = 'sudo -E -S {c} <<< "{i}"'.format(c=cmd, i=cmd_input) return self.exec_command(command, timeout, log_stdout_err=log_stdout_err) @@ -266,7 +267,7 @@ class SSH(object): .format(p=lxc_params, n=lxc_name, c=lxc_cmd) if sudo: - command = 'sudo -S {c}'.format(c=command) + command = 'sudo -E -S {c}'.format(c=command) return self.exec_command(command, timeout) def interactive_terminal_open(self, time_out=45): @@ -298,9 +299,8 @@ class SSH(object): if chan.exit_status_ready(): logger.error('Channel exit status ready') break - except socket.timeout: - logger.error('Socket timeout: {0}'.format(buf)) - raise Exception('Socket timeout: {0}'.format(buf)) + except socket.timeout as exc: + raise_from(Exception('Socket timeout: {0}'.format(buf)), exc) return chan def interactive_terminal_exec_command(self, chan, cmd, prompt): @@ -332,11 +332,10 @@ class SSH(object): if chan.exit_status_ready(): logger.error('Channel exit status ready') break - except socket.timeout: - logger.error('Socket timeout during execution of command: ' - '{0}\nBuffer content:\n{1}'.format(cmd, buf)) - raise Exception('Socket timeout during execution of command: ' - '{0}\nBuffer content:\n{1}'.format(cmd, buf)) + except socket.timeout as exc: + raise_from(Exception( + 'Socket timeout during execution of command: ' + '{0}\nBuffer content:\n{1}'.format(cmd, buf)), exc) tmp = buf.replace(cmd.replace('\n', ''), '') for item in prompt: tmp.replace(item, '') @@ -454,8 +453,8 @@ def exec_cmd(node, cmd, timeout=600, sudo=False, disconnect=False): if not sudo: (ret_code, stdout, stderr) = ssh.exec_command(cmd, timeout=timeout) else: - (ret_code, stdout, stderr) = ssh.exec_command_sudo(cmd, - timeout=timeout) + (ret_code, stdout, stderr) = ssh.exec_command_sudo( + cmd, timeout=timeout) except SSHException as err: logger.error(repr(err)) return None, None, None @@ -468,7 +467,7 @@ def exec_cmd(node, cmd, timeout=600, sudo=False, disconnect=False): def exec_cmd_no_error( node, cmd, timeout=600, sudo=False, message=None, disconnect=False, - retries=0): + retries=0, include_reason=False): """Convenience function to ssh/exec/return out & err. Verifies that return code is zero. @@ -483,6 +482,7 @@ def exec_cmd_no_error( :param message: Error message in case of failure. Default: None. :param disconnect: Close the opened SSH connection if True. :param retries: How many times to retry on failure. + :param include_reason: Whether default info should be appended to message. :type node: dict :type cmd: str or OptionString :type timeout: int @@ -490,6 +490,7 @@ def exec_cmd_no_error( :type message: str :type disconnect: bool :type retries: int + :type include_reason: bool :returns: Stdout, Stderr. :rtype: tuple(str, str) :raises RuntimeError: If bash return code is not 0. @@ -501,12 +502,19 @@ def exec_cmd_no_error( break sleep(1) else: - msg = ('Command execution failed: "{cmd}"\n{stderr}'. - format(cmd=cmd, stderr=stderr) if message is None else message) + msg = 'Command execution failed: "{cmd}"\nRC: {rc}\n{stderr}'.format( + cmd=cmd, rc=ret_code, stderr=stderr) + logger.info(msg) + if message: + if include_reason: + msg = message + '\n' + msg + else: + msg = message raise RuntimeError(msg) return stdout, stderr + def scp_node( node, local_path, remote_path, get=False, timeout=30, disconnect=False): """Copy files from local_path to remote_path or vice versa. @@ -531,14 +539,14 @@ def scp_node( try: ssh.connect(node) - except SSHException: - raise RuntimeError('Failed to connect to {host}!' - .format(host=node['host'])) + except SSHException as exc: + raise_from(RuntimeError( + 'Failed to connect to {host}!'.format(host=node['host'])), exc) try: ssh.scp(local_path, remote_path, get, timeout) - except SCPException: - raise RuntimeError('SCP execution failed on {host}!' - .format(host=node['host'])) + except SCPException as exc: + raise_from(RuntimeError( + 'SCP execution failed on {host}!'.format(host=node['host'])), exc) finally: if disconnect: ssh.disconnect()