fuel-qa/gates_tests/helpers/utils.py

532 lines
19 KiB
Python

# 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 itertools
import os
import yaml
from proboscis import register
from proboscis.asserts import assert_equal
from devops.helpers import helpers
from fuelweb_test.helpers.fuel_actions import BaseActions
from fuelweb_test.helpers.gerrit.gerrit_info_provider import \
FuelLibraryModulesProvider
from fuelweb_test.helpers.ssh_manager import SSHManager
from fuelweb_test import logger
from fuelweb_test import settings
from fuelweb_test.helpers.utils import YamlEditor
from gates_tests.helpers import exceptions
def replace_rpm_package(package):
"""Replaced rpm package.rpm on master node with package.rpm
from review
"""
ssh = SSHManager()
logger.info("Patching {}".format(package))
if not settings.UPDATE_FUEL:
raise exceptions.FuelQAVariableNotSet('UPDATE_FUEL', 'True')
try:
# Upload package
target_path = '/var/www/nailgun/{}/'.format(package)
ssh.upload_to_remote(
ip=ssh.admin_ip,
source=settings.UPDATE_FUEL_PATH.rstrip('/'),
target=target_path)
package_name = package
package_ext = '*.noarch.rpm'
pkg_path = os.path.join(target_path,
'{}{}'.format(package_name, package_ext))
full_package_name = get_full_filename(wildcard_name=pkg_path)
logger.debug('Package name is {0}'.format(full_package_name))
full_package_path = os.path.join(os.path.dirname(pkg_path),
full_package_name)
# Update package on master node
if not does_new_pkg_equal_to_installed_pkg(
installed_package=package_name,
new_package=full_package_path):
update_rpm(path=full_package_path)
except Exception:
logger.error("Could not upload package")
raise
def update_ostf():
logger.info("Uploading new package from {0}".format(
settings.UPDATE_FUEL_PATH))
ssh = SSHManager()
pack_path = '/var/www/nailgun/fuel-ostf/'
full_pack_path = os.path.join(pack_path, 'fuel-ostf*.noarch.rpm')
ssh.upload_to_remote(
ssh.admin_ip,
source=settings.UPDATE_FUEL_PATH.rstrip('/'), target=pack_path)
# Check old fuel-ostf package
cmd = "rpm -q fuel-ostf"
old_package = ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)['stdout_str']
logger.info(
'Current package version of '
'fuel-ostf: {0}'.format(old_package))
cmd = "rpm -qp {0}".format(full_pack_path)
new_package = ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)['stdout_str']
logger.info('Package from review {0}'.format(new_package))
if old_package == new_package:
logger.info('Package {0} is installed'.format(new_package))
return
cmd = "service ostf stop"
ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
cmd = "service ostf status"
helpers.wait(lambda: "dead" in ssh.execute_on_remote(
ssh.admin_ip, cmd=cmd,
raise_on_assert=False,
assert_ec_equal=[3])['stdout_str'], timeout=60)
logger.info("OSTF status: inactive")
cmd = "rpm -e fuel-ostf"
ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
cmd = "rpm -Uvh --oldpackage {0}".format(full_pack_path)
ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
cmd = "rpm -q fuel-ostf"
installed_package = ssh.execute_on_remote(
ssh.admin_ip, cmd=cmd)['stdout_str']
assert_equal(
installed_package, new_package,
"The new package {0} was not installed. Actual {1}".format(
new_package, installed_package))
cmd = "service ostf start"
ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
cmd = "service ostf status"
helpers.wait(
lambda: "running" in
ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)['stdout_str'],
timeout=60)
cmd = "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8777"
helpers.wait(
lambda: "401" in ssh.execute_on_remote(
ssh.admin_ip, cmd=cmd, raise_on_assert=False)['stdout_str'],
timeout=60)
logger.info("OSTF status: RUNNING")
def get_oswl_services_names():
cmd = "systemctl list-units| grep oswl_ | awk '{print $1}'"
result = SSHManager().execute_on_remote(
SSHManager().admin_ip, cmd)['stdout_str'].strip()
logger.info('list of statistic services {0}'.format(
result.split('\n')))
return result.split('\n')
def replace_fuel_nailgun_rpm():
"""
Replace fuel_nailgun*.rpm from review
"""
logger.info("Patching fuel-nailgun")
ssh = SSHManager()
if not settings.UPDATE_FUEL:
raise exceptions.FuelQAVariableNotSet('UPDATE_FUEL', 'True')
pack_path = '/var/www/nailgun/fuel-nailgun/'
full_pack_path = os.path.join(pack_path,
'fuel-nailgun*.noarch.rpm')
logger.info('Package path {0}'.format(full_pack_path))
ssh.upload_to_remote(
ip=ssh.admin_ip,
source=settings.UPDATE_FUEL_PATH.rstrip('/'), target=pack_path)
# Check old fuel-nailgun package
cmd = "rpm -q fuel-nailgun"
old_package = ssh.execute_on_remote(
ip=ssh.admin_ip, cmd=cmd)['stdout_str']
logger.info(
'Current package version of '
'fuel-nailgun: {0}'.format(old_package))
cmd = "rpm -qp {0}".format(full_pack_path)
new_package = ssh.execute_on_remote(
ip=ssh.admin_ip, cmd=cmd)['stdout_str']
logger.info("Updating package {0} with {1}".format(
old_package, new_package))
if old_package == new_package:
logger.debug('Looks like package from review '
'was installed during setups of master node')
return
# stop services
service_list = ['assassind', 'receiverd', 'nailgun', 'statsenderd']
for service in service_list:
ssh.execute_on_remote(
ip=ssh.admin_ip, cmd='systemctl stop {0}'.format(service))
logger.info('statistic services {0}'.format(get_oswl_services_names()))
# stop statistic services
for service in get_oswl_services_names():
ssh.execute_on_remote(
ip=ssh.admin_ip, cmd='systemctl stop {0}'.format(service))
# Drop nailgun db manage.py dropdb
cmd = 'manage.py dropdb'
ssh.execute_on_remote(ssh.admin_ip, cmd)
# Delete package
logger.info("Delete package {0}".format(old_package))
cmd = "rpm -e fuel-nailgun"
ssh.execute_on_remote(ssh.admin_ip, cmd)
logger.info("Install package {0}".format(new_package))
cmd = "rpm -Uvh --oldpackage {0}".format(full_pack_path)
ssh.execute_on_remote(ssh.admin_ip, cmd)
cmd = "rpm -q fuel-nailgun"
installed_package = ssh.execute_on_remote(ssh.admin_ip, cmd)['stdout_str']
assert_equal(installed_package, new_package,
"The new package {0} was not installed".format(new_package))
cmd = ('puppet apply --debug '
'/etc/puppet/modules/fuel/examples/nailgun.pp')
ssh.execute_on_remote(ssh.admin_ip, cmd)
cmd_sync = 'fuel release --sync-deployment-tasks --dir /etc/puppet/'
ssh.execute_on_remote(ssh.admin_ip, cmd=cmd_sync)
def update_rpm(path, rpm_cmd='/bin/rpm -Uvh --force'):
cmd = '{rpm_cmd} {rpm_path}'\
.format(rpm_cmd=rpm_cmd, rpm_path=path)
logger.info("Updating rpm '{0}'".format(path))
try:
SSHManager().execute(SSHManager().admin_ip, cmd)
logger.info("Rpm '{0}' has been updated successfully "
.format(path))
except Exception as ex:
logger.error("Could not update rpm '{0}' in the '{1}'"
.format(path, ex))
raise
def restart_service(service_name, timeout=30):
restart_cmd = 'service {} restart'.format(service_name)
get_status_cmd = 'service {} status'.format(service_name)
logger.info("Restarting service '{0}'".format(service_name))
try:
SSHManager().execute_on_remote(SSHManager().admin_ip,
restart_cmd)
helpers.wait(
lambda: 'running' in
SSHManager().execute_on_remote(SSHManager().admin_ip,
get_status_cmd)['stdout_str'],
timeout=timeout)
logger.info("Service '{0}' has been restarted successfully "
.format(service_name))
except Exception as ex:
logger.error("Could not restart '{0}' service "
"in the '{1}'"
.format(service_name, ex))
raise
def does_new_pkg_equal_to_installed_pkg(installed_package,
new_package):
rpm_query_cmd = '/bin/rpm -q'
current_version_cmd = '{rpm} {package}'\
.format(rpm=rpm_query_cmd, package=installed_package)
urlfile_version_cmd = '{rpm} --package {package}'\
.format(rpm=rpm_query_cmd, package=new_package)
logger.info("Comparing installed package version against "
"the package version to be installed")
current_version = SSHManager().execute_on_remote(
ip=SSHManager().admin_ip, cmd=current_version_cmd)['stdout_str']
new_version = SSHManager().execute_on_remote(
ip=SSHManager().admin_ip, cmd=urlfile_version_cmd)['stdout_str']
logger.info("Installed package version: {}".format(current_version))
logger.info("Package version to be installed: {}".format(new_version))
return current_version == new_version
def get_full_filename(wildcard_name):
cmd = 'ls {}'.format(wildcard_name)
logger.info("Getting full file name for: {}".format(wildcard_name))
full_pkg_name = SSHManager().execute_on_remote(
ip=SSHManager().admin_ip,
cmd=cmd)['stdout_str']
return full_pkg_name
def get_sha_sum(file_path):
logger.debug('Get md5 fo file {0}'.format(file_path))
md5_sum = SSHManager().execute_on_remote(
SSHManager().admin_ip, cmd='md5sum {0}'.format(
file_path))['stdout_str'].strip()
logger.info('MD5 is {0}'.format(md5_sum))
return md5_sum
def fuel_library_modules_mapping(modules):
"""
find fuel-qa system test which have maximum coverage for edited
puppet modules and register that group with "review_in_fuel_library" name
modules - dictionary of puppet modules edited in review
Example: modules = {'horizon':'fuel-library/deployment/Puppetfile'}
"""
# open yaml with covered modules
with open(
"gates_tests/helpers/fuel_library_modules_mapping.yaml", "r") as f:
mapping = yaml.load(f)
if modules and isinstance(modules, dict):
all_modules = set(list(itertools.chain.from_iterable(
[mapping[test_group]['modules'] for test_group in mapping])))
logger.debug(
"List of puppet modules covered by system_tests {}".format(
all_modules))
logger.info(
"List of modules edited in review {}".format(modules.keys()))
# checking that module from review covered by system_test
for module in modules.keys():
if module not in all_modules:
logger.warning(
"{}:{} module not exist or not covered by system_test"
.format(module, modules[module]))
# find test group which has better coverage of modules from review
system_test = "bvt_2"
max_intersection = 0
if not ("ceph" in modules and
{"roles/cinder.pp", "cinder", "openstack-cinder"} &
set(modules)):
for test in mapping:
test_intersection = len(
set(mapping[test]['modules']).intersection(set(modules)))
if test_intersection > max_intersection:
max_intersection = test_intersection
system_test = test
devops_template = mapping[system_test]['devops_settings_template']
import gates_tests
path_to_template = os.path.join(
os.path.dirname(os.path.abspath(gates_tests.__file__)),
devops_template)
logger.debug("devops template is {}".format(path_to_template))
os.environ['DEVOPS_SETTINGS_TEMPLATE'] = path_to_template
# To completely check ceph module we can't mix ceph and cinder togeher
else:
logger.warning(
"We cannot check cinder and ceph together {}"
.format(modules))
system_test = "bvt_2"
else:
logger.warning("There no modules that changed in review "
"so just run default system test")
system_test = "bvt_2"
logger.info(
"Puppet modules from review {}"
" will be checked by next system test: {}".format(
modules, system_test))
register(groups=['review_in_fuel_library'],
depends_on_groups=[system_test])
def openstack_puppet_project_mapping(project):
"""
find fuel-qa system test which have maximum coverage for edited
openstack/puppet-project and register that group with
"review_in_openstack_puppet_project" name
project - puppet project edited in review
Example: project = "openstack/puppet-openstacklib"
"""
# open yaml with covered projects
with open(
"gates_tests/helpers/openstack_puppet_projects_mapping.yaml",
"r") as f:
mapping = yaml.load(f)
all_projects = set(list(itertools.chain.from_iterable(
[mapping[test_group]['modules'] for test_group in mapping])))
logger.debug(
"List of openstack/puppet-projects "
"covered by system_tests {}".format(
all_projects))
logger.info(
"Edited project in review - '{}'".format(project))
# checking that project from review covered by system_test
if project not in all_projects:
logger.warning(
"{} project not exist or not covered by system_test"
.format(project))
# find test group which cover project edited in review
system_test = "bvt_2"
for test in mapping:
if project in mapping[test]['projects']:
system_test = test
break
devops_template = mapping[system_test]['devops_settings_template']
import gates_tests
path_to_template = os.path.join(
os.path.dirname(os.path.abspath(gates_tests.__file__)),
devops_template)
logger.debug("devops template is {}".format(path_to_template))
os.environ['DEVOPS_SETTINGS_TEMPLATE'] = path_to_template
logger.info(
"Edited project in review - '{}'"
" will be checked by next system test: {}".format(
project, system_test))
register(groups=['review_in_openstack_puppet_project'],
depends_on_groups=[system_test])
def map_test_review_in_fuel_library(**kwargs):
groups = kwargs.get('run_groups', [])
old_groups = kwargs.get('groups', None)
groups.extend(old_groups or [])
if 'review_in_fuel_library' in groups:
if settings.GERRIT_CHANGE_ID and settings.GERRIT_PATCHSET_NUMBER:
mp = FuelLibraryModulesProvider.from_environment_vars()
modules = mp.get_changed_modules()
else:
modules = dict()
fuel_library_modules_mapping(modules)
def map_test_review_in_openstack_puppet_projects(**kwargs):
groups = kwargs.get('run_groups', [])
old_groups = kwargs.get('groups', None)
groups.extend(old_groups or [])
if 'review_in_openstack_puppet_project' in groups:
if settings.GERRIT_PROJECT:
project = settings.GERRIT_PROJECT
else:
project = str()
openstack_puppet_project_mapping(project)
def check_package_version_injected_in_bootstraps(
package,
cluster_id=None,
ironic=None):
ssh = SSHManager()
try:
pack_path = '/var/www/nailgun/{}/'.format(package)
ssh.upload_to_remote(
ip=ssh.admin_ip,
source=settings.UPDATE_FUEL_PATH.rstrip('/'),
target=pack_path)
except Exception:
logger.exception("Could not upload package")
raise
# Step 1 - unpack active bootstrap
logger.info("unpack active bootstrap")
if ironic:
bootstrap = "/var/www/nailgun/bootstrap/ironic/{}".format(cluster_id)
else:
bootstrap = "/var/www/nailgun/bootstraps/active_bootstrap"
bootstrap_var = "/var/root.squashfs"
cmd = "unsquashfs -d {} {}/root.squashfs".format(
bootstrap_var, bootstrap)
ssh.execute_on_remote(
ip=ssh.admin_ip,
cmd=cmd)
# Step 2 - check package version
logger.info(
"check package {} version injected in ubuntu bootstrap".format(
package))
cmd = "ls {}|grep {} |grep deb |cut -f 2 -d '_'".format(
pack_path, package)
package_from_review = ssh.execute_on_remote(
ip=ssh.admin_ip,
cmd=cmd)['stdout_str']
logger.info("package from review is {}".format(package_from_review))
awk_pattern = "awk '{print $2}'"
cmd = "chroot {}/ /bin/bash -c \"dpkg -s {}\"|grep Version|{}".format(
bootstrap_var, package, awk_pattern)
installed_package = ssh.execute_on_remote(
ip=ssh.admin_ip,
cmd=cmd)['stdout_str']
logger.info("injected package is {}".format(installed_package))
assert_equal(installed_package, package_from_review,
"The new package {0} wasn't injected in bootstrap".format(
package_from_review))
# Step 3 - remove unpacked bootstrap
cmd = "rm -rf {}".format(bootstrap_var)
ssh.execute_on_remote(
ip=ssh.admin_ip,
cmd=cmd)
def update_bootstrap_cli_yaml():
actions = BaseActions()
path = "/etc/fuel-bootstrap-cli/fuel_bootstrap_cli.yaml"
astute_yaml_path = "/etc/fuel/astute.yaml"
with YamlEditor(astute_yaml_path, ip=actions.admin_ip) as editor:
repos = editor.content["BOOTSTRAP"]["repos"]
repos.append({
'name': 'auxiliary',
'priority': "1200",
'section': 'main restricted',
'suite': 'auxiliary',
'type': 'deb',
'uri': 'http://127.0.0.1:8080/ubuntu/auxiliary/'})
with YamlEditor(path, ip=actions.admin_ip) as editor:
editor.content['repos'] = repos