ceph/teuthology/run.py

187 lines
5.9 KiB
Python
Raw Normal View History

import os
import yaml
import StringIO
import contextlib
2013-08-29 19:01:04 +00:00
import sys
import logging
2013-08-29 19:01:04 +00:00
from traceback import format_tb
from . import report
from .misc import get_distro
from .misc import get_user
from .misc import read_config
from .nuke import nuke
from .run_tasks import run_tasks
from .results import email_results
2013-08-29 18:35:52 +00:00
def set_up_logging(ctx):
loglevel = logging.INFO
if ctx.verbose:
loglevel = logging.DEBUG
2013-08-29 18:35:52 +00:00
logging.basicConfig(level=loglevel)
if ctx.archive is not None:
os.mkdir(ctx.archive)
handler = logging.FileHandler(
filename=os.path.join(ctx.archive, 'teuthology.log'),
2013-08-29 18:35:52 +00:00
)
formatter = logging.Formatter(
fmt='%(asctime)s.%(msecs)03d %(levelname)s:%(name)s:%(message)s',
datefmt='%Y-%m-%dT%H:%M:%S',
2013-08-29 18:35:52 +00:00
)
handler.setFormatter(formatter)
logging.getLogger().addHandler(handler)
2013-08-29 19:01:04 +00:00
install_except_hook()
def install_except_hook():
def log_exception(exception_class, exception, traceback):
logging.critical(''.join(format_tb(traceback)))
if not exception.message:
logging.critical(exception_class.__name__)
return
logging.critical('{0}: {1}'.format(
exception_class.__name__, exception))
2013-08-29 19:01:04 +00:00
sys.excepthook = log_exception
2013-08-29 18:35:52 +00:00
def write_initial_metadata(ctx):
if ctx.archive is not None:
with file(os.path.join(ctx.archive, 'pid'), 'w') as f:
f.write('%d' % os.getpid())
with file(os.path.join(ctx.archive, 'owner'), 'w') as f:
f.write(ctx.owner + '\n')
with file(os.path.join(ctx.archive, 'orig.config.yaml'), 'w') as f:
yaml.safe_dump(ctx.config, f, default_flow_style=False)
info = {
'name': ctx.name,
'description': ctx.description,
'owner': ctx.owner,
'pid': os.getpid(),
}
2013-09-11 18:56:48 +00:00
if 'job_id' in ctx.config:
info['job_id'] = ctx.config['job_id']
with file(os.path.join(ctx.archive, 'info.yaml'), 'w') as f:
yaml.safe_dump(info, f, default_flow_style=False)
2013-08-29 18:35:52 +00:00
def main(ctx):
2013-08-29 18:35:52 +00:00
set_up_logging(ctx)
log = logging.getLogger(__name__)
if ctx.owner is None:
ctx.owner = get_user()
# Older versions of teuthology stored job_id as an int. Convert it to a str
# if necessary.
job_id = ctx.config.get('job_id')
if job_id is not None:
job_id = str(job_id)
ctx.config['job_id'] = job_id
2013-08-29 18:35:52 +00:00
write_initial_metadata(ctx)
report.try_push_job_info(ctx.config)
2013-08-29 18:35:52 +00:00
if 'targets' in ctx.config and 'roles' in ctx.config:
targets = len(ctx.config['targets'])
roles = len(ctx.config['roles'])
assert targets >= roles, \
'%d targets are needed for all roles but found %d listed.' % (
roles, targets)
machine_type = ctx.machine_type
if machine_type is None:
fallback_default = ctx.config.get('machine_type', 'plana')
machine_type = ctx.config.get('machine-type', fallback_default)
if ctx.block:
assert ctx.lock, \
'the --block option is only supported with the --lock option'
read_config(ctx)
log.debug('\n '.join(['Config:', ] + yaml.safe_dump(
ctx.config, default_flow_style=False).splitlines()))
ctx.summary = dict(success=True)
ctx.summary['owner'] = ctx.owner
if ctx.description is not None:
ctx.summary['description'] = ctx.description
for task in ctx.config['tasks']:
msg = ('kernel installation shouldn be a base-level item, not part ' +
'of the tasks list')
assert 'kernel' not in task, msg
init_tasks = []
if ctx.lock:
msg = ('You cannot specify targets in a config file when using the ' +
'--lock option')
assert 'targets' not in ctx.config, msg
init_tasks.append({'internal.lock_machines': (
len(ctx.config['roles']), machine_type)})
init_tasks.extend([
{'internal.save_config': None},
{'internal.check_lock': None},
{'internal.connect': None},
{'internal.check_conflict': None},
{'internal.check_ceph_data': None},
{'internal.vm_setup': None},
])
if 'kernel' in ctx.config:
distro = get_distro(ctx)
if distro == 'ubuntu':
init_tasks.append({'kernel': ctx.config['kernel']})
init_tasks.extend([
{'internal.base': None},
{'internal.archive': None},
{'internal.coredump': None},
{'internal.sudo': None},
{'internal.syslog': None},
{'internal.timer': None},
])
ctx.config['tasks'][:0] = init_tasks
try:
run_tasks(tasks=ctx.config['tasks'], ctx=ctx)
finally:
if not ctx.summary.get('success') and ctx.config.get('nuke-on-error'):
# only unlock if we locked them in the first place
nuke(ctx, log, ctx.lock)
if ctx.archive is not None:
with file(os.path.join(ctx.archive, 'summary.yaml'), 'w') as f:
yaml.safe_dump(ctx.summary, f, default_flow_style=False)
with contextlib.closing(StringIO.StringIO()) as f:
yaml.safe_dump(ctx.summary, f)
log.info('Summary data:\n%s' % f.getvalue())
with contextlib.closing(StringIO.StringIO()) as f:
if ('email-on-error' in ctx.config
and not ctx.summary.get('success', False)):
yaml.safe_dump(ctx.summary, f)
yaml.safe_dump(ctx.config, f)
emsg = f.getvalue()
subject = "Teuthology error -- %s" % ctx.summary[
'failure_reason']
email_results(subject, "Teuthology", ctx.config[
'email-on-error'], emsg)
report.try_push_job_info(ctx.config, ctx.summary)
if ctx.summary.get('success', True):
log.info('pass')
else:
log.info('FAIL')
sys.exit(1)