Switch to SSHClient API usage in execute_on_remote

Switch to SSHClient API usage in execute_on_remote: remote.check_call
check_call has been aligned to SSHClient

Change-Id: I6a6a0db5ccc1175c296a64d0c928d51558d51189
This commit is contained in:
Alexey Stepanov 2016-08-10 14:29:13 +03:00
parent 5e5d98a024
commit 8e90a5b653
5 changed files with 67 additions and 87 deletions

View File

@ -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():

View File

@ -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

View File

@ -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()

View File

@ -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))

View File

@ -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)