ceph/teuthology/suite.py
Sage Weil cfd5456f3f suite: support a suite consisting of multiple collections
suite = many collections, and maybe some shared files
collection = a collection of facets
facet = a config fragment
2011-08-18 16:30:08 -07:00

162 lines
4.7 KiB
Python

import argparse
import errno
import itertools
import logging
import os
import subprocess
import sys
log = logging.getLogger(__name__)
def main():
parser = argparse.ArgumentParser(description="""
Run a suite of ceph integration tests.
A suite is a directory containing a subdirectory collections/
containing collections.
A collection is a directory containing facets.
A facet is a directory containing config snippets.
Running the suite means running teuthology for every collection.
Running a collection means running teuthology for every configuration
combination generated by taking one config snippet from each facet.
Any config files passed on the command line will be used for every
combination, and will override anything in the suite.
""")
parser.add_argument(
'-v', '--verbose',
action='store_true', default=None,
help='be more verbose',
)
parser.add_argument(
'--suite',
metavar='DIR',
help='suite of tests to run',
required=True,
)
parser.add_argument(
'--owner',
help='job owner',
)
parser.add_argument(
'--name',
help='name for this suite',
required=True,
)
parser.add_argument(
'config',
metavar='CONFFILE',
nargs='*',
default=[],
help='config file to read',
)
args = parser.parse_args()
loglevel = logging.INFO
if args.verbose:
loglevel = logging.DEBUG
logging.basicConfig(
level=loglevel,
)
collection_dir = os.path.join(args.suite,'collections')
print collection_dir
if os.path.exists(collection_dir) and os.path.isdir(collection_dir):
collections = [
(os.path.join(collection_dir, f), f)
for f in sorted(os.listdir(collection_dir))
if not f.startswith('.')
and os.path.isdir(os.path.join(collection_dir, f))
]
else:
# degenerate case; 'suite' is actually a single collection
collections = [(args.suite, 'none')]
for collection, collection_name in sorted(collections):
log.info('Collection %s in %s' % (collection_name, collection))
facets = [
f for f in sorted(os.listdir(collection))
if not f.startswith('.')
and os.path.isdir(os.path.join(collection, f))
]
facet_configs = (
[(f, name, os.path.join(collection, f, name))
for name in sorted(os.listdir(os.path.join(collection, f)))
if not name.startswith('.')
and name.endswith('.yaml')
]
for f in facets
)
for configs in itertools.product(*facet_configs):
description = 'collection:%s ' % (collection_name);
description += ' '.join('{facet}:{name}'.format(
facet=facet, name=name)
for facet, name, path in configs)
log.info(
'Running teuthology-schedule with facets %s', description
)
arg = [
os.path.join(os.path.dirname(sys.argv[0]), 'teuthology-schedule'),
]
if args.verbose:
arg.append('-v')
if args.owner:
arg.extend(['--owner', args.owner])
arg.extend([
'--name', args.name,
'--description', description,
'--',
])
arg.extend(path for facet, name, path in configs)
arg.extend(args.config)
print arg
subprocess.check_call(
args=arg,
)
def ls():
parser = argparse.ArgumentParser(description='List teuthology job results')
parser.add_argument(
'--archive-dir',
metavar='DIR',
help='path under which to archive results',
required=True,
)
args = parser.parse_args()
import yaml
for j in sorted(os.listdir(args.archive_dir)):
if j.startswith('.'):
continue
summary = {}
try:
with file('%s/%s/summary.yaml' % (args.archive_dir, j)) as f:
g = yaml.safe_load_all(f)
for new in g:
summary.update(new)
except IOError, e:
if e.errno == errno.ENOENT:
print "%s (no summary.yaml)" % j
continue
else:
raise
print "{job} {success} {owner} {desc}".format(
job=j,
owner=summary.get('owner', '-'),
desc=summary.get('description', '-'),
success='pass' if summary['success'] else 'FAIL',
)