diff --git a/fuelweb_test/helpers/checkers.py b/fuelweb_test/helpers/checkers.py index 806dd5e4e..813a61691 100644 --- a/fuelweb_test/helpers/checkers.py +++ b/fuelweb_test/helpers/checkers.py @@ -156,14 +156,15 @@ def verify_network_list_api(os_conn, net_count=None): def check_ceph_image_size(ip, expected_size, device='vdc'): ret = ssh_manager.check_call( ip=ip, - cmd="df -m /dev/{device}* | grep ceph | awk" - " {size}".format(device=device, - size=re.escape('{print $2}')) - )['stdout'] + command="df -m /dev/{device}* | grep ceph | awk" + " {size}".format(device=device, + size=re.escape('{print $2}')) + ).stdout if not ret: - logger.error("Partition not present! {}: ".format( - ssh_manager.check_call(ip=ip, cmd="df -m"))) + logger.error( + "Partition not present! {}: ".format( + ssh_manager.check_call(ip=ip, command="df -m").stdout_str)) raise Exception() logger.debug("Partitions: {part}".format(part=ret)) assert_true(abs(float(ret[0].rstrip()) / expected_size - 1) < 0.1, @@ -238,7 +239,7 @@ def enable_feature_group(env, group): # update nailgun configs via puppet from that value ssh_manager.check_call( ip=ssh_manager.admin_ip, - cmd='puppet apply /etc/puppet/modules/fuel/examples/nailgun.pp' + command='puppet apply /etc/puppet/modules/fuel/examples/nailgun.pp' ) def check_api_group_enabled(): diff --git a/fuelweb_test/helpers/exceptions.py b/fuelweb_test/helpers/exceptions.py index 68e8e812d..ebb074b25 100644 --- a/fuelweb_test/helpers/exceptions.py +++ b/fuelweb_test/helpers/exceptions.py @@ -11,31 +11,3 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - - -class UnexpectedExitCode(Exception): - def __init__(self, command, ec, expected_ec, stdout=None, stderr=None): - """Exception for unexpected exit code after executing shell/ssh command - :param command: str - executed command - :param ec: int - actual exit code - :param expected_ec: list of integers - expected exit codes - :param stdout: str - :param stderr: str - """ - self.ec = ec - self.expected_ec = expected_ec - self.cmd = command - self.stdout = stdout - self.stderr = stderr - super(UnexpectedExitCode, self).__init__() - - def __str__(self): - message = "Command '{cmd:s}' returned unexpected exit code {code:d}," \ - " while waiting for {exp}".format(cmd=self.cmd, - code=self.ec, - exp=self.expected_ec) - if self.stdout: - message += "stdout: {}\n".format(self.stdout) - if self.stderr: - message += "stderr: {}\n".format(self.stderr) - return message diff --git a/fuelweb_test/helpers/ssh_manager.py b/fuelweb_test/helpers/ssh_manager.py index d7e1afd5c..7513bf9ef 100644 --- a/fuelweb_test/helpers/ssh_manager.py +++ b/fuelweb_test/helpers/ssh_manager.py @@ -17,6 +17,7 @@ import os import posixpath import re import traceback +from warnings import warn from devops.helpers.helpers import wait from devops.models.node import SSHClient @@ -26,7 +27,6 @@ import yaml from fuelweb_test import logger from fuelweb_test.helpers.metaclasses import SingletonMeta -from fuelweb_test.helpers.exceptions import UnexpectedExitCode @six.add_metaclass(SingletonMeta) @@ -85,8 +85,10 @@ class SSHManager(object): """ Function returns remote SSH connection to node by ip address :param ip: IP of host + :type ip: str :param port: port for SSH - :return: SSHClient + :type port: int + :rtype: SSHClient """ if (ip, port) not in self.connections: logger.debug('SSH_MANAGER:Create new connection for ' @@ -142,9 +144,34 @@ class SSHManager(object): remote = self._get_remote(ip=ip, port=port) return remote.execute(cmd) - def check_call(self, ip, cmd, port=22, verbose=False): + def check_call( + self, + ip, + command, port=22, verbose=False, timeout=None, + error_info=None, + expected=None, raise_on_err=True): + """Execute command and check for return code + + :type ip: str + :type command: str + :type port: int + :type verbose: bool + :type timeout: int + :type error_info: str + :type expected: list + :type raise_on_err: bool + :rtype: ExecResult + :raises: DevopsCalledProcessError + """ remote = self._get_remote(ip=ip, port=port) - return remote.check_call(cmd, verbose) + return remote.check_call( + command=command, + verbose=verbose, + timeout=timeout, + error_info=error_info, + expected=expected, + raise_on_err=raise_on_err + ) def execute_on_remote(self, ip, cmd, port=22, err_msg=None, jsonify=False, assert_ec_equal=None, @@ -168,11 +195,16 @@ class SSHManager(object): if yamlify and jsonify: raise ValueError('Conflicting arguments: yamlify and jsonify!') - orig_result = self.execute(ip=ip, port=port, cmd=cmd) + remote = self._get_remote(ip=ip, port=port) + orig_result = remote.check_call( + command=cmd, + error_info=err_msg, + expected=assert_ec_equal, + raise_on_err=raise_on_assert + ) # Now create fallback result # TODO(astepanov): switch to SSHClient output after tests adoptation - # TODO(astepanov): process whole parameters on SSHClient().check_call() result = { 'stdout': orig_result['stdout'], @@ -182,43 +214,10 @@ class SSHManager(object): 'stderr_str': ''.join(orig_result['stderr']).strip(), } - details_log = ( - "Host: {host}\n" - "Command: '{cmd}'\n" - "Exit code: {code}\n" - "STDOUT:\n{stdout}\n" - "STDERR:\n{stderr}".format( - host=ip, cmd=cmd, code=result['exit_code'], - stdout=result['stdout_str'], stderr=result['stderr_str'] - )) - - if result['exit_code'] not in assert_ec_equal: - error_msg = ( - err_msg or - "Unexpected exit_code returned: actual {0}, expected {1}." - "".format( - result['exit_code'], - ' '.join(map(str, assert_ec_equal)))) - log_msg = ( - "{0} Command: '{1}' " - "Details:\n{2}".format( - error_msg, cmd, details_log)) - logger.error(log_msg) - if raise_on_assert: - raise UnexpectedExitCode(cmd, - result['exit_code'], - assert_ec_equal, - stdout=result['stdout_str'], - stderr=result['stderr_str']) - else: - logger.debug(details_log) - if jsonify: - result['stdout_json'] = \ - self._json_deserialize(result['stdout_str']) + result['stdout_json'] = orig_result.stdout_json elif yamlify: - result['stdout_yaml'] = \ - self._yaml_deserialize(result['stdout_str']) + result['stdout_yaml'] = orig_result.stdout_yaml return result @@ -234,6 +233,10 @@ class SSHManager(object): :return: obj :raise: Exception """ + warn( + '_json_deserialize is not used anymore and will be removed later', + DeprecationWarning) + if isinstance(json_string, list): json_string = ''.join(json_string).strip() @@ -254,6 +257,10 @@ class SSHManager(object): :return: obj :raise: Exception """ + warn( + '_yaml_deserialize is not used anymore and will be removed later', + DeprecationWarning) + if isinstance(yaml_string, list): yaml_string = ''.join(yaml_string).strip() diff --git a/fuelweb_test/helpers/utils.py b/fuelweb_test/helpers/utils.py index 80d2762ec..e126cdbb0 100644 --- a/fuelweb_test/helpers/utils.py +++ b/fuelweb_test/helpers/utils.py @@ -1044,14 +1044,14 @@ def get_ceph_partitions(ip, device, fs_type="xfs"): # Moved from checkers.py for improvement of code ret = SSHManager().check_call( ip=ip, - cmd="parted {device} print | grep {type}".format(device=device, - type=fs_type) - )['stdout'] + command="parted {device} print | grep {type}".format(device=device, + type=fs_type) + ).stdout if not ret: logger.error( "Partition not present! {partitions}: ".format( partitions=SSHManager().check_call( - ip=ip, cmd="parted {device} print"))) + ip=ip, command="parted {device} print").stdout_str)) raise Exception() logger.debug("Partitions: {part}".format(part=ret)) return ret @@ -1062,7 +1062,7 @@ def get_mongo_partitions(ip, device): # Moved from checkers.py for improvement of code ret = SSHManager().check_call( ip=ip, - cmd="lsblk | grep {device} | awk {size}".format( + command="lsblk | grep {device} | awk {size}".format( device=device, size=re.escape('{print $4}')) )['stdout'] @@ -1070,7 +1070,7 @@ def get_mongo_partitions(ip, device): logger.error( "Partition not present! {partitions}: ".format( partitions=SSHManager().check_call( - ip=ip, cmd="parted {device} print"))) + ip=ip, command="parted {device} print").stdout_str)) raise Exception() logger.debug("Partitions: {part}".format(part=ret)) return ret @@ -1147,8 +1147,8 @@ def get_quantity_of_numa(ip): numa = int(SSHManager().check_call( ip=ip, - cmd="lstopo | grep NUMANode| wc -l" - )['stdout'][0]) + command="lstopo | grep NUMANode| wc -l" + ).stdout[0]) if not numa: logger.debug("There are no NUMA nodes on {0}".format(ip)) diff --git a/fuelweb_test/tests/test_ubuntu_bootstrap.py b/fuelweb_test/tests/test_ubuntu_bootstrap.py index 32dabaf52..edceab813 100644 --- a/fuelweb_test/tests/test_ubuntu_bootstrap.py +++ b/fuelweb_test/tests/test_ubuntu_bootstrap.py @@ -16,6 +16,7 @@ import textwrap from devops.helpers.helpers import tcp_ping from devops.helpers.helpers import wait +from devops.error import DevopsCalledProcessError from proboscis.asserts import assert_equal from proboscis.asserts import assert_not_equal from proboscis.asserts import assert_raises @@ -28,7 +29,6 @@ from fuelweb_test.helpers import utils from fuelweb_test.helpers.decorators import log_snapshot_after_test from fuelweb_test import settings from fuelweb_test.tests import base_test_case -from fuelweb_test.helpers.exceptions import UnexpectedExitCode @test(groups=["ubuntu_bootstrap_builder", "bvt_ubuntu_bootstrap"]) @@ -296,7 +296,7 @@ class UbuntuBootstrapBuild(base_test_case.TestBasic): "Bootstrap {0} was not deleted and still available: {1}" .format(uuid, bootstrap_uuids)) - assert_raises(UnexpectedExitCode, + assert_raises(DevopsCalledProcessError, self.env.fuel_bootstrap_actions.activate_bootstrap_image, uuid) @@ -311,7 +311,7 @@ class UbuntuBootstrapBuild(base_test_case.TestBasic): assert_true(uuid is not None, "No active bootstrap. Possibly centos " "is active or something went wrong.") assert_raises( - UnexpectedExitCode, + DevopsCalledProcessError, self.env.fuel_bootstrap_actions.delete_bootstrap_image, uuid)