mirror of
https://github.com/ceph/ceph
synced 2024-12-17 00:46:05 +00:00
Add calamari_nosetests task.
Includes all accumulated review commentary and final 'yum clean all' fix. Signed-off-by: Dan Mick <dan.mick@redhat.com>
This commit is contained in:
parent
1bba98bda2
commit
efa6c36f70
281
tasks/calamari_nosetests.py
Normal file
281
tasks/calamari_nosetests.py
Normal file
@ -0,0 +1,281 @@
|
||||
import contextlib
|
||||
import logging
|
||||
import os
|
||||
import textwrap
|
||||
import yaml
|
||||
|
||||
from teuthology import contextutil
|
||||
from teuthology import misc
|
||||
from teuthology import packaging
|
||||
from teuthology.orchestra import run
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# extra stuff we need to do our job here
|
||||
EXTRA_PKGS = [
|
||||
'git',
|
||||
]
|
||||
|
||||
# stuff that would be in a devmode install, but should be
|
||||
# installed in the system for running nosetests against
|
||||
# a production install.
|
||||
EXTRA_NOSETEST_PKGS = [
|
||||
'python-psutil',
|
||||
'python-mock',
|
||||
]
|
||||
|
||||
|
||||
def find_client0(cluster):
|
||||
''' Find remote that has client.0 role, or None '''
|
||||
for rem, roles in cluster.remotes.iteritems():
|
||||
if 'client.0' in roles:
|
||||
return rem
|
||||
return None
|
||||
|
||||
|
||||
def pip(remote, package, venv=None, uninstall=False, force=False):
|
||||
''' {un}install a package with pip, possibly in a virtualenv '''
|
||||
if venv:
|
||||
pip = os.path.join(venv, 'bin', 'pip')
|
||||
args = ['sudo', pip]
|
||||
else:
|
||||
args = ['sudo', 'pip']
|
||||
|
||||
if uninstall:
|
||||
args.extend(['uninstall', '-y'])
|
||||
else:
|
||||
args.append('install')
|
||||
if force:
|
||||
args.append('-I')
|
||||
|
||||
args.append(package)
|
||||
remote.run(args=args)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def install_epel(remote):
|
||||
''' install a disabled-by-default epel repo config file '''
|
||||
remove = False
|
||||
try:
|
||||
if remote.os.package_type == 'deb':
|
||||
yield
|
||||
else:
|
||||
remove = True
|
||||
distromajor = remote.os.version.split('.')[0]
|
||||
|
||||
repofiledata = textwrap.dedent('''
|
||||
[epel]
|
||||
name=epel{version}
|
||||
metalink=http://mirrors.fedoraproject.org/metalink?repo=epel-{version}&arch=$basearch
|
||||
enabled=0
|
||||
gpgcheck=0
|
||||
''').format(version=distromajor)
|
||||
|
||||
misc.create_file(remote, '/etc/yum.repos.d/epel.repo',
|
||||
data=repofiledata, sudo=True)
|
||||
remote.run(args='sudo yum clean all')
|
||||
yield
|
||||
|
||||
finally:
|
||||
if remove:
|
||||
misc.delete_file(remote, '/etc/yum.repos.d/epel.repo', sudo=True)
|
||||
|
||||
|
||||
def enable_epel(remote, enable=True):
|
||||
''' enable/disable the epel repo '''
|
||||
args = 'sudo sed -i'.split()
|
||||
if enable:
|
||||
args.extend(['s/enabled=0/enabled=1/'])
|
||||
else:
|
||||
args.extend(['s/enabled=1/enabled=0/'])
|
||||
args.extend(['/etc/yum.repos.d/epel.repo'])
|
||||
|
||||
remote.run(args=args)
|
||||
remote.run(args='sudo yum clean all')
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def install_extra_pkgs(client):
|
||||
''' Install EXTRA_PKGS '''
|
||||
try:
|
||||
for pkg in EXTRA_PKGS:
|
||||
packaging.install_package(pkg, client)
|
||||
yield
|
||||
|
||||
finally:
|
||||
for pkg in EXTRA_PKGS:
|
||||
packaging.remove_package(pkg, client)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def clone_calamari(config, client):
|
||||
''' clone calamari source into current directory on remote '''
|
||||
branch = config.get('calamari_branch', 'master')
|
||||
url = config.get('calamari_giturl', 'git://github.com/ceph/calamari')
|
||||
try:
|
||||
cmd = 'git clone -b {branch} {giturl}'.format(
|
||||
branch=branch, giturl=url
|
||||
)
|
||||
client.run(args=cmd)
|
||||
yield
|
||||
finally:
|
||||
# sudo python setup.py develop may have left some root files around
|
||||
client.run(args='sudo rm -rf calamari')
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def write_info_yaml(cluster, client):
|
||||
''' write info.yaml to client for nosetests '''
|
||||
try:
|
||||
info = {
|
||||
'cluster': {
|
||||
rem.name: {'roles': roles}
|
||||
for rem, roles in cluster.remotes.iteritems()
|
||||
}
|
||||
}
|
||||
misc.create_file(client, 'calamari/info.yaml',
|
||||
data=yaml.safe_dump(info, default_flow_style=False))
|
||||
yield
|
||||
finally:
|
||||
misc.delete_file(client, 'calamari/info.yaml')
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def write_test_conf(client):
|
||||
''' write calamari/tests/test.conf to client for nosetests '''
|
||||
try:
|
||||
testconf = textwrap.dedent('''
|
||||
[testing]
|
||||
|
||||
calamari_control = external
|
||||
ceph_control = external
|
||||
bootstrap = False
|
||||
api_username = admin
|
||||
api_password = admin
|
||||
embedded_timeout_factor = 1
|
||||
external_timeout_factor = 3
|
||||
external_cluster_path = info.yaml
|
||||
''')
|
||||
misc.create_file(client, 'calamari/tests/test.conf', data=testconf)
|
||||
yield
|
||||
|
||||
finally:
|
||||
misc.delete_file(client, 'calamari/tests/test.conf')
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def prepare_nosetest_env(client):
|
||||
try:
|
||||
# extra dependencies that would be in the devmode venv
|
||||
if client.os.package_type == 'rpm':
|
||||
enable_epel(client, enable=True)
|
||||
for package in EXTRA_NOSETEST_PKGS:
|
||||
packaging.install_package(package, client)
|
||||
if client.os.package_type == 'rpm':
|
||||
enable_epel(client, enable=False)
|
||||
|
||||
# install nose itself into the calamari venv, force it in case it's
|
||||
# already installed in the system, so we can invoke it by path without
|
||||
# fear that it's not present
|
||||
pip(client, 'nose', venv='/opt/calamari/venv', force=True)
|
||||
|
||||
# install a later version of requests into the venv as well
|
||||
# (for precise)
|
||||
pip(client, 'requests', venv='/opt/calamari/venv', force=True)
|
||||
|
||||
# link (setup.py develop) calamari/rest-api into the production venv
|
||||
# because production does not include calamari_rest.management, needed
|
||||
# for test_rest_api.py's ApiIntrospection
|
||||
args = 'cd calamari/rest-api'.split() + [run.Raw(';')] + \
|
||||
'sudo /opt/calamari/venv/bin/python setup.py develop'.split()
|
||||
client.run(args=args)
|
||||
|
||||
# because, at least in Python 2.6/Centos, site.py uses
|
||||
# 'os.path.exists()' to process .pth file entries, and exists() uses
|
||||
# access(2) to check for existence, all the paths leading up to
|
||||
# $HOME/calamari/rest-api need to be searchable by all users of
|
||||
# the package, which will include the WSGI/Django app, running
|
||||
# as the Apache user. So make them all world-read-and-execute.
|
||||
args = 'sudo chmod a+x'.split() + \
|
||||
['.', './calamari', './calamari/rest-api']
|
||||
client.run(args=args)
|
||||
|
||||
# make one dummy request just to get the WSGI app to do
|
||||
# all its log creation here, before the chmod below (I'm
|
||||
# looking at you, graphite -- /var/log/calamari/info.log and
|
||||
# /var/log/calamari/exception.log)
|
||||
client.run(args='wget -q -O /dev/null http://localhost')
|
||||
|
||||
# /var/log/calamari/* is root-or-apache write-only
|
||||
client.run(args='sudo chmod a+w /var/log/calamari/*')
|
||||
|
||||
yield
|
||||
|
||||
finally:
|
||||
args = 'cd calamari/rest-api'.split() + [run.Raw(';')] + \
|
||||
'sudo /opt/calamari/venv/bin/python setup.py develop -u'.split()
|
||||
client.run(args=args)
|
||||
for pkg in ('nose', 'requests'):
|
||||
pip(client, pkg, venv='/opt/calamari/venv', uninstall=True)
|
||||
for package in EXTRA_NOSETEST_PKGS:
|
||||
packaging.remove_package(package, client)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def run_nosetests(client):
|
||||
''' Actually run the tests '''
|
||||
args = [
|
||||
'cd',
|
||||
'calamari',
|
||||
run.Raw(';'),
|
||||
'CALAMARI_CONFIG=/etc/calamari/calamari.conf',
|
||||
'/opt/calamari/venv/bin/nosetests',
|
||||
'-v',
|
||||
'tests/',
|
||||
]
|
||||
client.run(args=args)
|
||||
yield
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def task(ctx, config):
|
||||
"""
|
||||
Run Calamari tests against an instance set up by 'calamari_server'.
|
||||
|
||||
-- clone the Calamari source into $HOME (see options)
|
||||
-- write calamari/info.yaml describing the cluster
|
||||
-- write calamari/tests/test.conf containing
|
||||
'external' for calamari_control and ceph_control
|
||||
'bootstrap = False' to disable test bootstrapping (installing minions)
|
||||
no api_url necessary (inferred from client.0)
|
||||
'external_cluster_path = info.yaml'
|
||||
-- modify the production Calamari install to allow test runs:
|
||||
install nose in the venv
|
||||
install EXTRA_NOSETEST_PKGS
|
||||
link in, with setup.py develop, calamari_rest (for ApiIntrospection)
|
||||
-- set CALAMARI_CONFIG to point to /etc/calamari/calamari.conf
|
||||
-- nosetests -v tests/
|
||||
|
||||
Options are:
|
||||
calamari_giturl: url from which to git clone calamari
|
||||
(default: git://github.com/ceph/calamari)
|
||||
calamari_branch: git branch of calamari to check out
|
||||
(default: master)
|
||||
|
||||
Note: the tests must find a clean cluster, so don't forget to
|
||||
set the crush default type appropriately, or install min_size OSD hosts
|
||||
"""
|
||||
client0 = find_client0(ctx.cluster)
|
||||
if client0 is None:
|
||||
raise RuntimeError("must have client.0 role")
|
||||
|
||||
with contextutil.nested(
|
||||
lambda: install_epel(client0),
|
||||
lambda: install_extra_pkgs(client0),
|
||||
lambda: clone_calamari(config, client0),
|
||||
lambda: write_info_yaml(ctx.cluster, client0),
|
||||
lambda: write_test_conf(client0),
|
||||
lambda: prepare_nosetest_env(client0),
|
||||
lambda: run_nosetests(client0),
|
||||
):
|
||||
yield
|
Loading…
Reference in New Issue
Block a user