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:
parent
5e5d98a024
commit
8e90a5b653
@ -156,14 +156,15 @@ def verify_network_list_api(os_conn, net_count=None):
|
|||||||
def check_ceph_image_size(ip, expected_size, device='vdc'):
|
def check_ceph_image_size(ip, expected_size, device='vdc'):
|
||||||
ret = ssh_manager.check_call(
|
ret = ssh_manager.check_call(
|
||||||
ip=ip,
|
ip=ip,
|
||||||
cmd="df -m /dev/{device}* | grep ceph | awk"
|
command="df -m /dev/{device}* | grep ceph | awk"
|
||||||
" {size}".format(device=device,
|
" {size}".format(device=device,
|
||||||
size=re.escape('{print $2}'))
|
size=re.escape('{print $2}'))
|
||||||
)['stdout']
|
).stdout
|
||||||
|
|
||||||
if not ret:
|
if not ret:
|
||||||
logger.error("Partition not present! {}: ".format(
|
logger.error(
|
||||||
ssh_manager.check_call(ip=ip, cmd="df -m")))
|
"Partition not present! {}: ".format(
|
||||||
|
ssh_manager.check_call(ip=ip, command="df -m").stdout_str))
|
||||||
raise Exception()
|
raise Exception()
|
||||||
logger.debug("Partitions: {part}".format(part=ret))
|
logger.debug("Partitions: {part}".format(part=ret))
|
||||||
assert_true(abs(float(ret[0].rstrip()) / expected_size - 1) < 0.1,
|
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
|
# update nailgun configs via puppet from that value
|
||||||
ssh_manager.check_call(
|
ssh_manager.check_call(
|
||||||
ip=ssh_manager.admin_ip,
|
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():
|
def check_api_group_enabled():
|
||||||
|
@ -11,31 +11,3 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# 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
|
|
||||||
|
@ -17,6 +17,7 @@ import os
|
|||||||
import posixpath
|
import posixpath
|
||||||
import re
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
|
from warnings import warn
|
||||||
|
|
||||||
from devops.helpers.helpers import wait
|
from devops.helpers.helpers import wait
|
||||||
from devops.models.node import SSHClient
|
from devops.models.node import SSHClient
|
||||||
@ -26,7 +27,6 @@ import yaml
|
|||||||
|
|
||||||
from fuelweb_test import logger
|
from fuelweb_test import logger
|
||||||
from fuelweb_test.helpers.metaclasses import SingletonMeta
|
from fuelweb_test.helpers.metaclasses import SingletonMeta
|
||||||
from fuelweb_test.helpers.exceptions import UnexpectedExitCode
|
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(SingletonMeta)
|
@six.add_metaclass(SingletonMeta)
|
||||||
@ -85,8 +85,10 @@ class SSHManager(object):
|
|||||||
""" Function returns remote SSH connection to node by ip address
|
""" Function returns remote SSH connection to node by ip address
|
||||||
|
|
||||||
:param ip: IP of host
|
:param ip: IP of host
|
||||||
|
:type ip: str
|
||||||
:param port: port for SSH
|
:param port: port for SSH
|
||||||
:return: SSHClient
|
:type port: int
|
||||||
|
:rtype: SSHClient
|
||||||
"""
|
"""
|
||||||
if (ip, port) not in self.connections:
|
if (ip, port) not in self.connections:
|
||||||
logger.debug('SSH_MANAGER:Create new connection for '
|
logger.debug('SSH_MANAGER:Create new connection for '
|
||||||
@ -142,9 +144,34 @@ class SSHManager(object):
|
|||||||
remote = self._get_remote(ip=ip, port=port)
|
remote = self._get_remote(ip=ip, port=port)
|
||||||
return remote.execute(cmd)
|
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)
|
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,
|
def execute_on_remote(self, ip, cmd, port=22, err_msg=None,
|
||||||
jsonify=False, assert_ec_equal=None,
|
jsonify=False, assert_ec_equal=None,
|
||||||
@ -168,11 +195,16 @@ class SSHManager(object):
|
|||||||
if yamlify and jsonify:
|
if yamlify and jsonify:
|
||||||
raise ValueError('Conflicting arguments: 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
|
# Now create fallback result
|
||||||
# TODO(astepanov): switch to SSHClient output after tests adoptation
|
# TODO(astepanov): switch to SSHClient output after tests adoptation
|
||||||
# TODO(astepanov): process whole parameters on SSHClient().check_call()
|
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
'stdout': orig_result['stdout'],
|
'stdout': orig_result['stdout'],
|
||||||
@ -182,43 +214,10 @@ class SSHManager(object):
|
|||||||
'stderr_str': ''.join(orig_result['stderr']).strip(),
|
'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:
|
if jsonify:
|
||||||
result['stdout_json'] = \
|
result['stdout_json'] = orig_result.stdout_json
|
||||||
self._json_deserialize(result['stdout_str'])
|
|
||||||
elif yamlify:
|
elif yamlify:
|
||||||
result['stdout_yaml'] = \
|
result['stdout_yaml'] = orig_result.stdout_yaml
|
||||||
self._yaml_deserialize(result['stdout_str'])
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -234,6 +233,10 @@ class SSHManager(object):
|
|||||||
:return: obj
|
:return: obj
|
||||||
:raise: Exception
|
:raise: Exception
|
||||||
"""
|
"""
|
||||||
|
warn(
|
||||||
|
'_json_deserialize is not used anymore and will be removed later',
|
||||||
|
DeprecationWarning)
|
||||||
|
|
||||||
if isinstance(json_string, list):
|
if isinstance(json_string, list):
|
||||||
json_string = ''.join(json_string).strip()
|
json_string = ''.join(json_string).strip()
|
||||||
|
|
||||||
@ -254,6 +257,10 @@ class SSHManager(object):
|
|||||||
:return: obj
|
:return: obj
|
||||||
:raise: Exception
|
:raise: Exception
|
||||||
"""
|
"""
|
||||||
|
warn(
|
||||||
|
'_yaml_deserialize is not used anymore and will be removed later',
|
||||||
|
DeprecationWarning)
|
||||||
|
|
||||||
if isinstance(yaml_string, list):
|
if isinstance(yaml_string, list):
|
||||||
yaml_string = ''.join(yaml_string).strip()
|
yaml_string = ''.join(yaml_string).strip()
|
||||||
|
|
||||||
|
@ -1044,14 +1044,14 @@ def get_ceph_partitions(ip, device, fs_type="xfs"):
|
|||||||
# Moved from checkers.py for improvement of code
|
# Moved from checkers.py for improvement of code
|
||||||
ret = SSHManager().check_call(
|
ret = SSHManager().check_call(
|
||||||
ip=ip,
|
ip=ip,
|
||||||
cmd="parted {device} print | grep {type}".format(device=device,
|
command="parted {device} print | grep {type}".format(device=device,
|
||||||
type=fs_type)
|
type=fs_type)
|
||||||
)['stdout']
|
).stdout
|
||||||
if not ret:
|
if not ret:
|
||||||
logger.error(
|
logger.error(
|
||||||
"Partition not present! {partitions}: ".format(
|
"Partition not present! {partitions}: ".format(
|
||||||
partitions=SSHManager().check_call(
|
partitions=SSHManager().check_call(
|
||||||
ip=ip, cmd="parted {device} print")))
|
ip=ip, command="parted {device} print").stdout_str))
|
||||||
raise Exception()
|
raise Exception()
|
||||||
logger.debug("Partitions: {part}".format(part=ret))
|
logger.debug("Partitions: {part}".format(part=ret))
|
||||||
return ret
|
return ret
|
||||||
@ -1062,7 +1062,7 @@ def get_mongo_partitions(ip, device):
|
|||||||
# Moved from checkers.py for improvement of code
|
# Moved from checkers.py for improvement of code
|
||||||
ret = SSHManager().check_call(
|
ret = SSHManager().check_call(
|
||||||
ip=ip,
|
ip=ip,
|
||||||
cmd="lsblk | grep {device} | awk {size}".format(
|
command="lsblk | grep {device} | awk {size}".format(
|
||||||
device=device,
|
device=device,
|
||||||
size=re.escape('{print $4}'))
|
size=re.escape('{print $4}'))
|
||||||
)['stdout']
|
)['stdout']
|
||||||
@ -1070,7 +1070,7 @@ def get_mongo_partitions(ip, device):
|
|||||||
logger.error(
|
logger.error(
|
||||||
"Partition not present! {partitions}: ".format(
|
"Partition not present! {partitions}: ".format(
|
||||||
partitions=SSHManager().check_call(
|
partitions=SSHManager().check_call(
|
||||||
ip=ip, cmd="parted {device} print")))
|
ip=ip, command="parted {device} print").stdout_str))
|
||||||
raise Exception()
|
raise Exception()
|
||||||
logger.debug("Partitions: {part}".format(part=ret))
|
logger.debug("Partitions: {part}".format(part=ret))
|
||||||
return ret
|
return ret
|
||||||
@ -1147,8 +1147,8 @@ def get_quantity_of_numa(ip):
|
|||||||
|
|
||||||
numa = int(SSHManager().check_call(
|
numa = int(SSHManager().check_call(
|
||||||
ip=ip,
|
ip=ip,
|
||||||
cmd="lstopo | grep NUMANode| wc -l"
|
command="lstopo | grep NUMANode| wc -l"
|
||||||
)['stdout'][0])
|
).stdout[0])
|
||||||
|
|
||||||
if not numa:
|
if not numa:
|
||||||
logger.debug("There are no NUMA nodes on {0}".format(ip))
|
logger.debug("There are no NUMA nodes on {0}".format(ip))
|
||||||
|
@ -16,6 +16,7 @@ import textwrap
|
|||||||
|
|
||||||
from devops.helpers.helpers import tcp_ping
|
from devops.helpers.helpers import tcp_ping
|
||||||
from devops.helpers.helpers import wait
|
from devops.helpers.helpers import wait
|
||||||
|
from devops.error import DevopsCalledProcessError
|
||||||
from proboscis.asserts import assert_equal
|
from proboscis.asserts import assert_equal
|
||||||
from proboscis.asserts import assert_not_equal
|
from proboscis.asserts import assert_not_equal
|
||||||
from proboscis.asserts import assert_raises
|
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.helpers.decorators import log_snapshot_after_test
|
||||||
from fuelweb_test import settings
|
from fuelweb_test import settings
|
||||||
from fuelweb_test.tests import base_test_case
|
from fuelweb_test.tests import base_test_case
|
||||||
from fuelweb_test.helpers.exceptions import UnexpectedExitCode
|
|
||||||
|
|
||||||
|
|
||||||
@test(groups=["ubuntu_bootstrap_builder", "bvt_ubuntu_bootstrap"])
|
@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}"
|
"Bootstrap {0} was not deleted and still available: {1}"
|
||||||
.format(uuid, bootstrap_uuids))
|
.format(uuid, bootstrap_uuids))
|
||||||
|
|
||||||
assert_raises(UnexpectedExitCode,
|
assert_raises(DevopsCalledProcessError,
|
||||||
self.env.fuel_bootstrap_actions.activate_bootstrap_image,
|
self.env.fuel_bootstrap_actions.activate_bootstrap_image,
|
||||||
uuid)
|
uuid)
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ class UbuntuBootstrapBuild(base_test_case.TestBasic):
|
|||||||
assert_true(uuid is not None, "No active bootstrap. Possibly centos "
|
assert_true(uuid is not None, "No active bootstrap. Possibly centos "
|
||||||
"is active or something went wrong.")
|
"is active or something went wrong.")
|
||||||
assert_raises(
|
assert_raises(
|
||||||
UnexpectedExitCode,
|
DevopsCalledProcessError,
|
||||||
self.env.fuel_bootstrap_actions.delete_bootstrap_image,
|
self.env.fuel_bootstrap_actions.delete_bootstrap_image,
|
||||||
uuid)
|
uuid)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user