Merge "Introduction of new method of SSH connection"
This commit is contained in:
commit
c5bc4943b1
|
@ -117,3 +117,8 @@ Utils
|
|||
-----
|
||||
.. automodule:: fuelweb_test.helpers.utils
|
||||
:members:
|
||||
|
||||
SSH Manager
|
||||
-----------
|
||||
.. automodule:: fuelweb_test.helpers.ssh_manager
|
||||
:members:
|
||||
|
|
|
@ -342,23 +342,22 @@ def retry(count=3, delay=30):
|
|||
def custom_repo(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
with args[0].environment.d_env.get_admin_remote() as remote:
|
||||
custom_pkgs = CustomRepo(remote)
|
||||
try:
|
||||
if settings.CUSTOM_PKGS_MIRROR:
|
||||
custom_pkgs.prepare_repository()
|
||||
custom_pkgs = CustomRepo()
|
||||
try:
|
||||
if settings.CUSTOM_PKGS_MIRROR:
|
||||
custom_pkgs.prepare_repository()
|
||||
|
||||
except Exception:
|
||||
logger.error("Unable to get custom packages from {0}\n{1}"
|
||||
.format(settings.CUSTOM_PKGS_MIRROR,
|
||||
traceback.format_exc()))
|
||||
raise
|
||||
except Exception:
|
||||
logger.error("Unable to get custom packages from {0}\n{1}"
|
||||
.format(settings.CUSTOM_PKGS_MIRROR,
|
||||
traceback.format_exc()))
|
||||
raise
|
||||
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception:
|
||||
custom_pkgs.check_puppet_logs()
|
||||
raise
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception:
|
||||
custom_pkgs.check_puppet_logs()
|
||||
raise
|
||||
return wrapper
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ from fuelweb_test.helpers.decorators import retry
|
|||
from fuelweb_test.helpers.regenerate_repo import regenerate_centos_repo
|
||||
from fuelweb_test.helpers.regenerate_repo import regenerate_ubuntu_repo
|
||||
from fuelweb_test.helpers import replace_repos
|
||||
from fuelweb_test.helpers.utils import cond_upload
|
||||
from fuelweb_test.helpers.ssh_manager import SSHManager
|
||||
from fuelweb_test.settings import MASTER_IS_CENTOS7
|
||||
from fuelweb_test.settings import FUEL_PLUGIN_BUILDER_REPO
|
||||
from fuelweb_test.settings import FUEL_USE_LOCAL_NTPD
|
||||
|
@ -43,8 +43,9 @@ from fuelweb_test.settings import NESSUS_IMAGE_PATH
|
|||
class BaseActions(object):
|
||||
"""BaseActions.""" # TODO documentation
|
||||
|
||||
def __init__(self, admin_remote):
|
||||
self.admin_remote = admin_remote
|
||||
def __init__(self):
|
||||
self.ssh_manager = SSHManager()
|
||||
self.admin_ip = self.ssh_manager.admin_ip
|
||||
self.container = None
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -62,7 +63,11 @@ class BaseActions(object):
|
|||
cmd = 'dockerctl shell {0} {1}'.format(container, command)
|
||||
if stdin is not None:
|
||||
cmd = 'echo "{0}" | {1}'.format(stdin, cmd)
|
||||
result = self.admin_remote.execute(cmd)
|
||||
|
||||
result = self.ssh_manager.execute_on_remote(
|
||||
ip=self.admin_ip,
|
||||
cmd=cmd
|
||||
)
|
||||
if exit_code is not None:
|
||||
assert_equal(exit_code,
|
||||
result['exit_code'],
|
||||
|
@ -93,7 +98,10 @@ class BaseActions(object):
|
|||
Standard output from console
|
||||
"""
|
||||
cmd = 'dockerctl copy {0} {1}'.format(copy_from, copy_to)
|
||||
result = self.admin_remote.execute(cmd)
|
||||
result = self.ssh_manager.execute_on_remote(
|
||||
ip=self.admin_ip,
|
||||
cmd=cmd
|
||||
)
|
||||
assert_equal(0, result['exit_code'],
|
||||
('Command copy returned exit code "{e}", but '
|
||||
'expected "0". Output: {out}; {err} ').format(
|
||||
|
@ -105,8 +113,10 @@ class BaseActions(object):
|
|||
|
||||
@property
|
||||
def is_container_ready(self):
|
||||
result = self.admin_remote.execute("timeout 5 dockerctl check {0}"
|
||||
.format(self.container))
|
||||
result = self.ssh_manager.execute_on_remote(
|
||||
ip=self.admin_ip,
|
||||
cmd="timeout 5 dockerctl check {0}".format(self.container)
|
||||
)
|
||||
return result['exit_code'] == 0
|
||||
|
||||
def wait_for_ready_container(self, timeout=300):
|
||||
|
@ -179,9 +189,17 @@ class BaseActions(object):
|
|||
|
||||
self.copy_between_node_and_container(
|
||||
'{0}:{1}'.format(container, path_to_file), old_file)
|
||||
self.admin_remote.download(old_file, old_file)
|
||||
self.ssh_manager.download_from_remote(
|
||||
ip=self.admin_ip,
|
||||
destination=old_file,
|
||||
target=old_file
|
||||
)
|
||||
self.put_value_to_local_yaml(old_file, new_file, element, value)
|
||||
self.admin_remote.upload(new_file, new_file)
|
||||
self.ssh_manager.upload_to_remote(
|
||||
ip=self.admin_ip,
|
||||
source=new_file,
|
||||
target=new_file
|
||||
)
|
||||
self.copy_between_node_and_container(
|
||||
new_file, '{0}:{1}'.format(container, path_to_file))
|
||||
os.remove(old_file)
|
||||
|
@ -204,8 +222,11 @@ class BaseActions(object):
|
|||
admin_tmp_file = path_to_file
|
||||
|
||||
host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
|
||||
|
||||
self.admin_remote.download(admin_tmp_file, host_tmp_file)
|
||||
self.ssh_manager.download_from_remote(
|
||||
ip=self.admin_ip,
|
||||
destination=admin_tmp_file,
|
||||
target=host_tmp_file
|
||||
)
|
||||
value = self.get_value_from_local_yaml(host_tmp_file, element)
|
||||
os.remove(host_tmp_file)
|
||||
return value
|
||||
|
@ -228,11 +249,18 @@ class BaseActions(object):
|
|||
admin_tmp_file = path_to_file
|
||||
|
||||
host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
|
||||
|
||||
self.admin_remote.download(admin_tmp_file, host_tmp_file)
|
||||
self.ssh_manager.download_from_remote(
|
||||
ip=self.admin_ip,
|
||||
destination=admin_tmp_file,
|
||||
target=host_tmp_file
|
||||
)
|
||||
self.put_value_to_local_yaml(host_tmp_file, host_tmp_file,
|
||||
element, value)
|
||||
self.admin_remote.upload(host_tmp_file, admin_tmp_file)
|
||||
self.ssh_manager.upload_to_remote(
|
||||
ip=self.admin_ip,
|
||||
source=host_tmp_file,
|
||||
target=admin_tmp_file
|
||||
)
|
||||
if self.container:
|
||||
self.copy_between_node_and_container(
|
||||
admin_tmp_file, '{0}:{1}'.format(self.container, path_to_file))
|
||||
|
@ -242,8 +270,8 @@ class BaseActions(object):
|
|||
class AdminActions(BaseActions):
|
||||
""" All actions relating to the admin node."""
|
||||
|
||||
def __init__(self, admin_remote):
|
||||
super(AdminActions, self).__init__(admin_remote)
|
||||
def __init__(self):
|
||||
super(AdminActions, self).__init__()
|
||||
|
||||
@logwrap
|
||||
def modify_configs(self, router):
|
||||
|
@ -258,7 +286,8 @@ class AdminActions(BaseActions):
|
|||
# for admin node
|
||||
cmd = 'ntpdate -p 4 -t 0.2 -ub {0}'.format(router)
|
||||
|
||||
if not self.admin_remote.execute(cmd)['exit_code']:
|
||||
if not self.ssh_manager.execute_on_remote(ip=self.admin_ip,
|
||||
cmd=cmd)['exit_code']:
|
||||
# Local ntpd on the host is alive, so
|
||||
# remove all NTP sources and add the host instead.
|
||||
logger.info("Switching NTPD on the Fuel admin node to use "
|
||||
|
@ -290,43 +319,53 @@ class AdminActions(BaseActions):
|
|||
ubuntu_files_count = 0
|
||||
|
||||
if centos_repo_path:
|
||||
centos_files_count = cond_upload(
|
||||
self.admin_remote, local_packages_dir,
|
||||
os.path.join(centos_repo_path, 'Packages'),
|
||||
"(?i).*\.rpm$")
|
||||
centos_files_count = self.ssh_manager.cond_upload(
|
||||
ip=self.admin_ip,
|
||||
source=local_packages_dir,
|
||||
target=os.path.join(centos_repo_path, 'Packages'),
|
||||
condition="(?i).*\.rpm$"
|
||||
)
|
||||
if centos_files_count > 0:
|
||||
regenerate_centos_repo(self.admin_remote, centos_repo_path)
|
||||
regenerate_centos_repo(centos_repo_path)
|
||||
|
||||
if ubuntu_repo_path:
|
||||
ubuntu_files_count = cond_upload(
|
||||
self.admin_remote, local_packages_dir,
|
||||
os.path.join(ubuntu_repo_path, 'pool/main'),
|
||||
"(?i).*\.deb$")
|
||||
ubuntu_files_count = self.ssh_manager.cond_upload(
|
||||
ip=self.admin_ip,
|
||||
source=local_packages_dir,
|
||||
target=os.path.join(ubuntu_repo_path, 'pool/main'),
|
||||
condition="(?i).*\.deb$"
|
||||
)
|
||||
if ubuntu_files_count > 0:
|
||||
regenerate_ubuntu_repo(self.admin_remote, ubuntu_repo_path)
|
||||
regenerate_ubuntu_repo(ubuntu_repo_path)
|
||||
|
||||
return centos_files_count, ubuntu_files_count
|
||||
|
||||
@logwrap
|
||||
def clean_generated_image(self, distro):
|
||||
images = ''.join(
|
||||
self.admin_remote.execute(
|
||||
"find /var/www/nailgun/targetimages/ -name"
|
||||
" 'env*{}*' -printf '%P\n'".format(distro.lower())))
|
||||
out = self.ssh_manager.execute_on_remote(
|
||||
ip=self.admin_ip,
|
||||
cmd="find /var/www/nailgun/targetimages/ -name "
|
||||
"'env*{}*' -printf '%P\n'".format(distro.lower())
|
||||
)
|
||||
images = ''.join(out)
|
||||
|
||||
logger.debug("images are {}".format(images))
|
||||
self.admin_remote.execute(
|
||||
"find /var/www/nailgun/targetimages/ -name 'env*{}*'"
|
||||
" -delete".format(distro.lower()))
|
||||
self.ssh_manager.execute_on_remote(
|
||||
ip=self.admin_ip,
|
||||
cmd="find /var/www/nailgun/targetimages/ -name 'env*{}*'"
|
||||
" -delete".format(distro.lower())
|
||||
)
|
||||
|
||||
@logwrap
|
||||
@retry(2)
|
||||
def untar(self, node_ssh, name, path):
|
||||
def untar(self, node_ip, name, path):
|
||||
logger.info('Unpacking file')
|
||||
filename, ext = os.path.splitext(name)
|
||||
cmd = "tar -xpvf" if ext.endswith("tar") else "lrzuntar"
|
||||
result = node_ssh.execute(
|
||||
'cd {0} && {2} {1}'.format(path, name, cmd))
|
||||
result = self.ssh_manager.execute_on_remote(
|
||||
ip=node_ip,
|
||||
cmd='cd {0} && {2} {1}'.format(path, name, cmd)
|
||||
)
|
||||
stdout, stderr = ''.join(result['stdout']), ''.join(result['stderr'])
|
||||
logger.debug('Result from tar command is {0}\n{1}'.format(stdout,
|
||||
stderr))
|
||||
|
@ -334,6 +373,7 @@ class AdminActions(BaseActions):
|
|||
|
||||
def upgrade_master_node(self, rollback=False, file_upload=True):
|
||||
"""This method upgrades master node with current state."""
|
||||
# TODO: It will be remooved or changed
|
||||
|
||||
master = self.admin_remote
|
||||
if file_upload:
|
||||
|
@ -367,8 +407,10 @@ class AdminActions(BaseActions):
|
|||
|
||||
def get_fuel_settings(self):
|
||||
cmd = 'cat {cfg_file}'.format(cfg_file=hlp_data.FUEL_SETTINGS_YAML)
|
||||
result = self.admin_remote.execute(cmd)
|
||||
|
||||
result = self.ssh_manager.execute_on_remote(
|
||||
ip=self.admin_ip,
|
||||
cmd=cmd
|
||||
)
|
||||
if result['exit_code'] == 0:
|
||||
fuel_settings = yaml.load(''.join(result['stdout']))
|
||||
else:
|
||||
|
@ -382,7 +424,10 @@ class AdminActions(BaseActions):
|
|||
default_style='"',
|
||||
default_flow_style=False),
|
||||
hlp_data.FUEL_SETTINGS_YAML)
|
||||
result = self.admin_remote.execute(cmd)
|
||||
result = self.ssh_manager.execute_on_remote(
|
||||
ip=self.admin_ip,
|
||||
cmd=cmd
|
||||
)
|
||||
assert_equal(result['exit_code'], 0,
|
||||
"Saving Fuel settings failed: {0}!".format(result))
|
||||
|
||||
|
@ -390,8 +435,8 @@ class AdminActions(BaseActions):
|
|||
class NailgunActions(BaseActions):
|
||||
"""NailgunActions.""" # TODO documentation
|
||||
|
||||
def __init__(self, admin_remote):
|
||||
super(NailgunActions, self).__init__(admin_remote)
|
||||
def __init__(self):
|
||||
super(NailgunActions, self).__init__()
|
||||
self.container = 'nailgun'
|
||||
|
||||
def update_nailgun_settings_once(self, settings):
|
||||
|
@ -461,8 +506,8 @@ class NailgunActions(BaseActions):
|
|||
class PostgresActions(BaseActions):
|
||||
"""PostgresActions.""" # TODO documentation
|
||||
|
||||
def __init__(self, admin_remote):
|
||||
super(PostgresActions, self).__init__(admin_remote)
|
||||
def __init__(self):
|
||||
super(PostgresActions, self).__init__()
|
||||
self.container = 'postgres'
|
||||
|
||||
def run_query(self, db, query):
|
||||
|
@ -493,8 +538,8 @@ class FuelPluginBuilder(BaseActions):
|
|||
|
||||
Initializes BaseActions.
|
||||
"""
|
||||
def __init__(self, admin_remote):
|
||||
super(FuelPluginBuilder, self).__init__(admin_remote)
|
||||
def __init__(self):
|
||||
super(FuelPluginBuilder, self).__init__()
|
||||
self.container = 'nailgun'
|
||||
|
||||
def fpb_install(self):
|
||||
|
@ -562,7 +607,11 @@ class FuelPluginBuilder(BaseActions):
|
|||
"""
|
||||
self.execute_in_container(
|
||||
"rm -rf {0}".format(remote_file), self.container)
|
||||
self.admin_remote.upload(local_file, "/tmp/temp.file")
|
||||
self.ssh_manager.upload_to_remote(
|
||||
ip=self.admin_ip,
|
||||
source=local_file,
|
||||
target="/tmp/temp.file"
|
||||
)
|
||||
self.copy_between_node_and_container(
|
||||
'/tmp/temp.file', '{0}:{1}'.format(self.container, remote_file))
|
||||
|
||||
|
@ -594,8 +643,8 @@ class FuelPluginBuilder(BaseActions):
|
|||
class CobblerActions(BaseActions):
|
||||
"""CobblerActions.""" # TODO documentation
|
||||
|
||||
def __init__(self, admin_remote):
|
||||
super(CobblerActions, self).__init__(admin_remote)
|
||||
def __init__(self):
|
||||
super(CobblerActions, self).__init__()
|
||||
self.container = 'cobbler'
|
||||
|
||||
def add_dns_upstream_server(self, dns_server_ip):
|
||||
|
@ -613,18 +662,22 @@ class CobblerActions(BaseActions):
|
|||
class DockerActions(object):
|
||||
"""DockerActions.""" # TODO documentation
|
||||
|
||||
def __init__(self, admin_remote):
|
||||
self.admin_remote = admin_remote
|
||||
def __init__(self):
|
||||
self.ssh_manager = SSHManager()
|
||||
|
||||
def list_containers(self):
|
||||
return self.admin_remote.execute('dockerctl list')['stdout']
|
||||
result = self.ssh_manager.execute_on_remote(
|
||||
ip=self.ssh_manager.admin_ip,
|
||||
cmd='dockerctl list'
|
||||
)
|
||||
return result['stdout']
|
||||
|
||||
def wait_for_ready_containers(self, timeout=300):
|
||||
if MASTER_IS_CENTOS7:
|
||||
return
|
||||
cont_actions = []
|
||||
for container in self.list_containers():
|
||||
cont_action = BaseActions(self.admin_remote)
|
||||
cont_action = BaseActions(self.ssh_manager)
|
||||
cont_action.container = container
|
||||
cont_actions.append(cont_action)
|
||||
try:
|
||||
|
@ -639,8 +692,11 @@ class DockerActions(object):
|
|||
.format(failed_containers, timeout))
|
||||
|
||||
def restart_container(self, container):
|
||||
self.admin_remote.execute('dockerctl restart {0}'.format(container))
|
||||
cont_action = BaseActions(self.admin_remote)
|
||||
self.ssh_manager.execute_on_remote(
|
||||
ip=self.ssh_manager.admin_ip,
|
||||
cmd='dockerctl restart {0}'.format(container)
|
||||
)
|
||||
cont_action = BaseActions(self.ssh_manager)
|
||||
cont_action.container = container
|
||||
cont_action.wait_for_ready_container()
|
||||
|
||||
|
@ -650,8 +706,10 @@ class DockerActions(object):
|
|||
|
||||
def execute_in_containers(self, cmd):
|
||||
for container in self.list_containers():
|
||||
self.admin_remote.execute(
|
||||
"dockerctl shell {0} bash -c '{1}'".format(container, cmd))
|
||||
self.ssh_manager.execute_on_remote(
|
||||
ip=self.ssh_manager.admin_ip,
|
||||
cmd="dockerctl shell {0} bash -c '{1}'".format(container, cmd)
|
||||
)
|
||||
|
||||
|
||||
class NessusActions(object):
|
||||
|
|
|
@ -23,19 +23,20 @@ from xml.etree import ElementTree
|
|||
|
||||
from fuelweb_test import logger
|
||||
from fuelweb_test import settings
|
||||
from fuelweb_test.helpers.utils import install_pkg
|
||||
from fuelweb_test.helpers.utils import install_pkg_2
|
||||
from fuelweb_test.helpers.ssh_manager import SSHManager
|
||||
|
||||
|
||||
def regenerate_ubuntu_repo(remote, path):
|
||||
def regenerate_ubuntu_repo(path):
|
||||
# Ubuntu
|
||||
cr = CustomRepo(remote)
|
||||
cr = CustomRepo()
|
||||
cr.install_tools(['dpkg', 'dpkg-devel', 'dpkg-dev'])
|
||||
cr.regenerate_repo('regenerate_ubuntu_repo', path)
|
||||
|
||||
|
||||
def regenerate_centos_repo(remote, path):
|
||||
def regenerate_centos_repo(path):
|
||||
# CentOS
|
||||
cr = CustomRepo(remote)
|
||||
cr = CustomRepo()
|
||||
cr.install_tools(['createrepo'])
|
||||
cr.regenerate_repo('regenerate_centos_repo', path)
|
||||
|
||||
|
@ -43,8 +44,9 @@ def regenerate_centos_repo(remote, path):
|
|||
class CustomRepo(object):
|
||||
"""CustomRepo.""" # TODO documentation
|
||||
|
||||
def __init__(self, remote):
|
||||
self.remote = remote
|
||||
def __init__(self):
|
||||
self.ssh_manager = SSHManager()
|
||||
self.ip = self.ssh_manager.admin_ip
|
||||
self.path_scripts = ('{0}/fuelweb_test/helpers/'
|
||||
.format(os.environ.get("WORKSPACE", "./")))
|
||||
self.remote_path_scripts = '/tmp/'
|
||||
|
@ -111,7 +113,10 @@ class CustomRepo(object):
|
|||
logger.info("Installing necessary tools for {0}"
|
||||
.format(settings.OPENSTACK_RELEASE))
|
||||
for master_tool in master_tools:
|
||||
exit_code = install_pkg(self.remote, master_tool)
|
||||
exit_code = install_pkg_2(
|
||||
ip=self.ip,
|
||||
pkg_name=master_tool
|
||||
)
|
||||
assert_equal(0, exit_code, 'Cannot install package {0} '
|
||||
'on admin node.'.format(master_tool))
|
||||
|
||||
|
@ -241,7 +246,10 @@ class CustomRepo(object):
|
|||
.format(pkgs_local_path + path_suff,
|
||||
self.custom_pkgs_mirror,
|
||||
pkg["filename:"])
|
||||
wget_result = self.remote.execute(wget_cmd)
|
||||
wget_result = self.ssh_manager.execute_on_remote(
|
||||
ip=self.ip,
|
||||
cmd=wget_cmd
|
||||
)
|
||||
assert_equal(0, wget_result['exit_code'],
|
||||
self.assert_msg(wget_cmd, wget_result['stderr']))
|
||||
|
||||
|
@ -250,12 +258,16 @@ class CustomRepo(object):
|
|||
# Uploading scripts that prepare local repositories:
|
||||
# 'regenerate_centos_repo' and 'regenerate_ubuntu_repo'
|
||||
try:
|
||||
self.remote.upload('{0}/{1}'.format(self.path_scripts,
|
||||
regenerate_script),
|
||||
self.remote_path_scripts)
|
||||
self.remote.execute('chmod 755 {0}/{1}'
|
||||
.format(self.remote_path_scripts,
|
||||
regenerate_script))
|
||||
self.ssh_manager.upload_to_remote(
|
||||
ip=self.ip,
|
||||
source='{0}/{1}'.format(self.path_scripts, regenerate_script),
|
||||
target=self.remote_path_scripts
|
||||
)
|
||||
self.ssh_manager.execute_on_remote(
|
||||
ip=self.ip,
|
||||
cmd='chmod 755 {0}/{1}'.format(self.remote_path_scripts,
|
||||
regenerate_script)
|
||||
)
|
||||
except Exception:
|
||||
logger.error('Could not upload scripts for updating repositories.'
|
||||
'\n{0}'.format(traceback.format_exc()))
|
||||
|
@ -266,7 +278,10 @@ class CustomRepo(object):
|
|||
regenerate_script,
|
||||
local_mirror_path,
|
||||
self.ubuntu_release)
|
||||
script_result = self.remote.execute(script_cmd)
|
||||
script_result = self.ssh_manager.execute_on_remote(
|
||||
ip=self.ip,
|
||||
cmd=script_cmd
|
||||
)
|
||||
assert_equal(0, script_result['exit_code'],
|
||||
self.assert_msg(script_cmd, script_result['stderr']))
|
||||
|
||||
|
@ -301,7 +316,10 @@ class CustomRepo(object):
|
|||
cmd = ('fgrep -h -e " Depends: " -e "{0}" -e "{1}" '
|
||||
'/var/log/docker-logs/remote/node-*/'
|
||||
'puppet*.log'.format(err_start, err_end))
|
||||
result = self.remote.execute(cmd)['stdout']
|
||||
result = self.ssh_manager.execute_on_remote(
|
||||
ip=self.ip,
|
||||
cmd=cmd
|
||||
)['stdout']
|
||||
|
||||
err_deps = {}
|
||||
err_deps_key = ''
|
||||
|
@ -338,7 +356,10 @@ class CustomRepo(object):
|
|||
|
||||
cmd = ('fgrep -h -e "Error: Package: " -e " Requires: " /var/log/'
|
||||
'docker-logs/remote/node-*/puppet*.log')
|
||||
result = self.remote.execute(cmd)['stdout']
|
||||
result = self.ssh_manager.execute_on_remote(
|
||||
ip=self.ip,
|
||||
cmd=cmd
|
||||
)['stdout']
|
||||
|
||||
err_deps = {}
|
||||
err_deps_key = ''
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
# Copyright 2015 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import posixpath
|
||||
import re
|
||||
|
||||
from paramiko import RSAKey
|
||||
from devops.models.node import SSHClient
|
||||
from fuelweb_test import logger
|
||||
|
||||
|
||||
class SingletonMeta(type):
|
||||
def __init__(cls, name, bases, dict):
|
||||
super(SingletonMeta, cls).__init__(name, bases, dict)
|
||||
cls.instance = None
|
||||
|
||||
def __call__(self, *args, **kw):
|
||||
if self.instance is None:
|
||||
self.instance = super(SingletonMeta, self).__call__(*args, **kw)
|
||||
return self.instance
|
||||
|
||||
def __getattr__(cls, name):
|
||||
return getattr(cls(), name)
|
||||
|
||||
|
||||
class SSHManager(object):
|
||||
__metaclass__ = SingletonMeta
|
||||
|
||||
def __init__(self):
|
||||
logger.debug('SSH_MANAGER: Run constructor SSHManager')
|
||||
self.connections = {}
|
||||
self.admin_ip = None
|
||||
self.admin_port = None
|
||||
self.login = None
|
||||
self.password = None
|
||||
|
||||
def initialize(self, admin_ip, login, password):
|
||||
""" It will be moved to __init__
|
||||
|
||||
:param admin_ip: ip address of admin node
|
||||
:param login: user name
|
||||
:param password: password for user
|
||||
:return: None
|
||||
"""
|
||||
self.admin_ip = admin_ip
|
||||
self.admin_port = 22
|
||||
self.login = login
|
||||
self.password = password
|
||||
|
||||
def _connect(self, remote):
|
||||
""" Check if connection is stable and return this one
|
||||
|
||||
:param remote:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
remote.execute("cd ~")
|
||||
except Exception:
|
||||
remote.reconnect()
|
||||
return remote
|
||||
|
||||
def _get_keys(self):
|
||||
keys = []
|
||||
admin_remote = self._get_remote(self.admin_ip)
|
||||
for key_string in ['/root/.ssh/id_rsa', '/root/.ssh/bootstrap.rsa']:
|
||||
with admin_remote.open(key_string) as f:
|
||||
keys.append(RSAKey.from_private_key(f))
|
||||
return keys
|
||||
|
||||
def _get_remote(self, ip, port=22):
|
||||
""" Function returns remote SSH connection to node by ip address
|
||||
|
||||
:param ip: IP of host
|
||||
:param port: port for SSH
|
||||
:return: SSHClient
|
||||
"""
|
||||
if (ip, port) not in self.connections:
|
||||
logger.debug('SSH_MANAGER:Create new connection for '
|
||||
'{ip}:{port}'.format(ip=ip, port=port))
|
||||
|
||||
keys = self._get_keys() if ip != self.admin_ip else []
|
||||
|
||||
self.connections[(ip, port)] = SSHClient(
|
||||
host=ip,
|
||||
port=port,
|
||||
username=self.login,
|
||||
password=self.password,
|
||||
private_keys=keys
|
||||
)
|
||||
logger.debug('SSH_MANAGER:Return existed connection for '
|
||||
'{ip}:{port}'.format(ip=ip, port=port))
|
||||
logger.debug('SSH_MANAGER: Connections {0}'.format(self.connections))
|
||||
return self._connect(self.connections[(ip, port)])
|
||||
|
||||
def execute_on_remote(self, ip, cmd, port=22):
|
||||
remote = self._get_remote(ip=ip, port=port)
|
||||
return remote.execute(cmd)
|
||||
|
||||
def open_on_remote(self, ip, path, mode='r', port=22):
|
||||
remote = self._get_remote(ip=ip, port=port)
|
||||
return remote.open(path, mode)
|
||||
|
||||
def upload_to_remote(self, ip, source, target, port=22):
|
||||
remote = self._get_remote(ip=ip, port=port)
|
||||
return remote.upload(source, target)
|
||||
|
||||
def download_from_remote(self, ip, destination, target, port=22):
|
||||
remote = self._get_remote(ip=ip, port=port)
|
||||
return remote.download(destination, target)
|
||||
|
||||
def exist_on_remote(self, ip, path, port=22):
|
||||
remote = self._get_remote(ip=ip, port=port)
|
||||
return remote.exist(path)
|
||||
|
||||
def isdir_on_remote(self, ip, path, port=22):
|
||||
remote = self._get_remote(ip=ip, port=port)
|
||||
return remote.isdir(path)
|
||||
|
||||
def isfile_on_remote(self, ip, path, port=22):
|
||||
remote = self._get_remote(ip=ip, port=port)
|
||||
return remote.isfile(path)
|
||||
|
||||
def mkdir_on_remote(self, ip, path, port=22):
|
||||
remote = self._get_remote(ip=ip, port=port)
|
||||
return remote.mkdir(path)
|
||||
|
||||
def rm_rf_on_remote(self, ip, path, port=22):
|
||||
remote = self._get_remote(ip=ip, port=port)
|
||||
return remote.rm_rf(path)
|
||||
|
||||
def cond_upload(self, ip, source, target, port=22, condition=''):
|
||||
""" Upload files only if condition in regexp matches filenames
|
||||
|
||||
:param ip: host ip
|
||||
:param source: source path
|
||||
:param target: destination path
|
||||
:param port: ssh port
|
||||
:param condition: regexp condition
|
||||
:return: count of files
|
||||
"""
|
||||
|
||||
# remote = self._get_remote(ip=ip, port=port)
|
||||
# maybe we should use SSHClient function. e.g. remote.isdir(target)
|
||||
# we can move this function to some *_actions class
|
||||
if self.isdir_on_remote(ip=ip, port=port, path=target):
|
||||
target = posixpath.join(target, os.path.basename(source))
|
||||
|
||||
source = os.path.expanduser(source)
|
||||
if not os.path.isdir(source):
|
||||
if re.match(condition, source):
|
||||
self.upload_to_remote(ip=ip, port=port,
|
||||
source=source, target=target)
|
||||
logger.debug("File '{0}' uploaded to the remote folder"
|
||||
" '{1}'".format(source, target))
|
||||
return 1
|
||||
else:
|
||||
logger.debug("Pattern '{0}' doesn't match the file '{1}', "
|
||||
"uploading skipped".format(condition, source))
|
||||
return 0
|
||||
|
||||
files_count = 0
|
||||
for rootdir, subdirs, files in os.walk(source):
|
||||
targetdir = os.path.normpath(
|
||||
os.path.join(
|
||||
target,
|
||||
os.path.relpath(rootdir, source))).replace("\\", "/")
|
||||
|
||||
self.mkdir_on_remote(ip=ip, port=port, path=targetdir)
|
||||
|
||||
for entry in files:
|
||||
local_path = os.path.join(rootdir, entry)
|
||||
remote_path = posixpath.join(targetdir, entry)
|
||||
if re.match(condition, local_path):
|
||||
self.upload_to_remote(ip=ip,
|
||||
port=port,
|
||||
source=local_path,
|
||||
target=remote_path)
|
||||
files_count += 1
|
||||
logger.debug("File '{0}' uploaded to the "
|
||||
"remote folder '{1}'".format(source, target))
|
||||
else:
|
||||
logger.debug("Pattern '{0}' doesn't match the file '{1}', "
|
||||
"uploading skipped".format(condition,
|
||||
local_path))
|
||||
return files_count
|
|
@ -29,6 +29,7 @@ from proboscis import asserts
|
|||
from fuelweb_test import logger
|
||||
from fuelweb_test import logwrap
|
||||
from fuelweb_test import settings
|
||||
from fuelweb_test.helpers.ssh_manager import SSHManager
|
||||
from fuelweb_test.settings import MASTER_IS_CENTOS7
|
||||
from gates_tests.helpers import exceptions
|
||||
|
||||
|
@ -302,6 +303,34 @@ def install_pkg(remote, pkg_name):
|
|||
return remote_status['exit_code']
|
||||
|
||||
|
||||
def install_pkg_2(ip, pkg_name, port=22):
|
||||
"""Install a package <pkg_name> on node
|
||||
:param ip: ip of node
|
||||
:param pkg_name: name of a package
|
||||
:param port: ssh port
|
||||
:return: exit code of installation
|
||||
"""
|
||||
ssh_manager = SSHManager()
|
||||
remote_status = ssh_manager.execute_on_remote(
|
||||
ip=ip,
|
||||
port=port,
|
||||
cmd="rpm -q '{0}'".format(pkg_name)
|
||||
)
|
||||
if remote_status['exit_code'] == 0:
|
||||
logger.info("Package '{0}' already installed.".format(pkg_name))
|
||||
else:
|
||||
logger.info("Installing package '{0}' ...".format(pkg_name))
|
||||
remote_status = ssh_manager.execute_on_remote(
|
||||
ip=ip,
|
||||
port=port,
|
||||
cmd="yum -y install {0}".format(pkg_name)
|
||||
)
|
||||
logger.info("Installation of the package '{0}' has been"
|
||||
" completed with exit code {1}"
|
||||
.format(pkg_name, remote_status['exit_code']))
|
||||
return remote_status['exit_code']
|
||||
|
||||
|
||||
def cond_upload(remote, source, target, condition=''):
|
||||
# Upload files only if condition in regexp matches filenames
|
||||
if remote.isdir(target):
|
||||
|
|
|
@ -37,6 +37,7 @@ from fuelweb_test.helpers.fuel_actions import NailgunActions
|
|||
from fuelweb_test.helpers.fuel_actions import PostgresActions
|
||||
from fuelweb_test.helpers.fuel_actions import NessusActions
|
||||
from fuelweb_test.helpers.ntp import GroupNtpSync
|
||||
from fuelweb_test.helpers.ssh_manager import SSHManager
|
||||
from fuelweb_test.helpers.utils import run_on_remote
|
||||
from fuelweb_test.helpers.utils import TimeStat
|
||||
from fuelweb_test.helpers import multiple_networks_hacks
|
||||
|
@ -66,11 +67,23 @@ class EnvironmentModel(object):
|
|||
self._fuel_web = None
|
||||
if not hasattr(self, "_config"):
|
||||
self._config = None
|
||||
self.ssh_manager = SSHManager()
|
||||
self.ssh_manager.initialize(
|
||||
self.get_admin_node_ip(),
|
||||
login=settings.SSH_CREDENTIALS['login'],
|
||||
password=settings.SSH_CREDENTIALS['password']
|
||||
)
|
||||
self.admin_actions = AdminActions()
|
||||
self.base_actions = BaseActions()
|
||||
self.cobbler_actions = CobblerActions()
|
||||
self.docker_actions = DockerActions()
|
||||
self.nailgun_actions = NailgunActions()
|
||||
self.postgres_actions = PostgresActions()
|
||||
|
||||
@property
|
||||
def fuel_web(self):
|
||||
if self._fuel_web is None:
|
||||
self._fuel_web = FuelWebClient(self.get_admin_node_ip(), self)
|
||||
self._fuel_web = FuelWebClient(self)
|
||||
return self._fuel_web
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -83,30 +96,6 @@ class EnvironmentModel(object):
|
|||
obj_id=obj_id,
|
||||
ip=ip)
|
||||
|
||||
@property
|
||||
def admin_actions(self):
|
||||
return AdminActions(self.d_env.get_admin_remote())
|
||||
|
||||
@property
|
||||
def base_actions(self):
|
||||
return BaseActions(self.d_env.get_admin_remote())
|
||||
|
||||
@property
|
||||
def nailgun_actions(self):
|
||||
return NailgunActions(self.d_env.get_admin_remote())
|
||||
|
||||
@property
|
||||
def postgres_actions(self):
|
||||
return PostgresActions(self.d_env.get_admin_remote())
|
||||
|
||||
@property
|
||||
def cobbler_actions(self):
|
||||
return CobblerActions(self.d_env.get_admin_remote())
|
||||
|
||||
@property
|
||||
def docker_actions(self):
|
||||
return DockerActions(self.d_env.get_admin_remote())
|
||||
|
||||
@property
|
||||
def admin_node_ip(self):
|
||||
return self.fuel_web.admin_node_ip
|
||||
|
|
|
@ -23,6 +23,7 @@ from devops.error import DevopsCalledProcessError
|
|||
from devops.error import TimeoutError
|
||||
from devops.helpers.helpers import _wait
|
||||
from devops.helpers.helpers import wait
|
||||
from fuelweb_test.helpers.ssh_manager import SSHManager
|
||||
from fuelweb_test.helpers.ssl import copy_cert_from_master
|
||||
from fuelweb_test.helpers.ssl import change_cluster_ssl_config
|
||||
from ipaddr import IPNetwork
|
||||
|
@ -86,9 +87,10 @@ from fuelweb_test.settings import iface_alias
|
|||
class FuelWebClient(object):
|
||||
"""FuelWebClient.""" # TODO documentation
|
||||
|
||||
def __init__(self, admin_node_ip, environment):
|
||||
self.admin_node_ip = admin_node_ip
|
||||
self.client = NailgunClient(admin_node_ip)
|
||||
def __init__(self, environment):
|
||||
self.ssh_manager = SSHManager()
|
||||
self.admin_node_ip = self.ssh_manager.admin_ip
|
||||
self.client = NailgunClient(self.ssh_manager.admin_ip)
|
||||
self._environment = environment
|
||||
self.security = SecurityChecks(self.client, self._environment)
|
||||
super(FuelWebClient, self).__init__()
|
||||
|
|
|
@ -20,6 +20,7 @@ from fuelweb_test import logger
|
|||
from fuelweb_test.helpers.decorators import log_snapshot_after_test
|
||||
from fuelweb_test.helpers.utils import get_test_method_name
|
||||
from fuelweb_test.helpers.utils import TimeStat
|
||||
from fuelweb_test.helpers.ssh_manager import SSHManager
|
||||
from fuelweb_test.models.environment import EnvironmentModel
|
||||
from fuelweb_test.settings import REPLACE_DEFAULT_REPOS
|
||||
from fuelweb_test.settings import REPLACE_DEFAULT_REPOS_ONLY_ONCE
|
||||
|
@ -32,8 +33,9 @@ class TestBasic(object):
|
|||
|
||||
"""
|
||||
def __init__(self):
|
||||
self.env = EnvironmentModel()
|
||||
self._current_log_step = 0
|
||||
self.ssh_manager = SSHManager()
|
||||
self.env = EnvironmentModel()
|
||||
|
||||
@property
|
||||
def test_program(self):
|
||||
|
|
|
@ -269,21 +269,22 @@ class CommandLineTest(test_cli_base.CommandLine):
|
|||
'Some slaves do not become online after revert!!'
|
||||
' Expected {0} Actual {1}'.format(nodes, online_nodes))
|
||||
|
||||
with self.env.d_env.get_admin_remote() as remote:
|
||||
res = remote.execute('fuel --env {0} env delete'
|
||||
.format(cluster_id))
|
||||
assert_true(
|
||||
res['exit_code'] == 0)
|
||||
res = self.ssh_manager.execute_on_remote(
|
||||
ip=self.ssh_manager.admin_ip,
|
||||
cmd='fuel --env {0} env delete'.format(cluster_id)
|
||||
)
|
||||
assert_true(res['exit_code'] == 0)
|
||||
|
||||
with self.env.d_env.get_admin_remote() as remote:
|
||||
try:
|
||||
wait(lambda:
|
||||
remote.execute("fuel env | awk '{print $1}'"
|
||||
" | tail -n 1 | grep '^.$'")
|
||||
['exit_code'] == 1, timeout=60 * 10)
|
||||
except TimeoutError:
|
||||
raise TimeoutError(
|
||||
"cluster {0} was not deleted".format(cluster_id))
|
||||
try:
|
||||
wait(lambda:
|
||||
self.ssh_manager.execute_on_remote(
|
||||
ip=self.ssh_manager.admin_ip,
|
||||
cmd="fuel env | awk '{print $1}' | tail -n 1 | "
|
||||
"grep '^.$'"
|
||||
)['exit_code'] == 1, timeout=60 * 10)
|
||||
except TimeoutError:
|
||||
raise TimeoutError(
|
||||
"cluster {0} was not deleted".format(cluster_id))
|
||||
|
||||
assert_false(
|
||||
check_cluster_presence(cluster_id, self.env.postgres_actions),
|
||||
|
|
Loading…
Reference in New Issue