blob: abc6bb0aa1406603c4862e7dbaedef72b363ca25 [file] [log] [blame]
import os
import uuid
import logging
import functools
import yaml
try:
from petname import Generate as pet_generate
except ImportError:
def pet_generate(x, y):
return str(uuid.uuid4())
import pretty_yaml
class NoData(object):
@classmethod
def get(cls, name, x):
return cls
class Config(object):
def __init__(self, val=None):
if val is not None:
self.update(val)
def get(self, name, defval=None):
obj = self.__dict__
for cname in name.split("."):
obj = obj.get(cname, NoData)
if obj is NoData:
return defval
return obj
def update(self, val):
self.__dict__.update(val)
def get_test_files(results_dir):
in_var_dir = functools.partial(os.path.join, results_dir)
res = dict(
run_params_file='run_params.yaml',
saved_config_file='config.yaml',
vm_ids_fname='os_vm_ids',
html_report_file='{0}_report.html',
load_report_file='load_report.html',
text_report_file='report.txt',
log_file='log.txt',
sensor_storage='sensor_storage',
nodes_report_file='nodes.yaml',
results_storage='results',
hwinfo_directory='hwinfo',
hwreport_fname='hwinfo.txt',
raw_results='raw_results.yaml')
res = dict((k, in_var_dir(v)) for k, v in res.items())
res['results_dir'] = results_dir
return res
def load_config(file_name):
file_name = os.path.abspath(file_name)
defaults = dict(
sensors_remote_path='/tmp/sensors',
testnode_log_root='/tmp/wally',
settings={}
)
raw_cfg = yaml.load(open(file_name).read())
raw_cfg['config_folder'] = os.path.dirname(file_name)
if 'include' in raw_cfg:
default_path = os.path.join(raw_cfg['config_folder'],
raw_cfg.pop('include'))
default_cfg = yaml.load(open(default_path).read())
# TODO: Need more intelectual configs merge?
default_cfg.update(raw_cfg)
raw_cfg = default_cfg
cfg = Config(defaults)
cfg.update(raw_cfg)
results_storage = cfg.settings.get('results_storage', '/tmp')
results_storage = os.path.abspath(results_storage)
existing = file_name.startswith(results_storage)
if existing:
cfg.results_dir = os.path.dirname(file_name)
cfg.run_uuid = os.path.basename(cfg.results_dir)
else:
# genarate result folder name
for i in range(10):
cfg.run_uuid = pet_generate(2, "_")
cfg.results_dir = os.path.join(results_storage,
cfg.run_uuid)
if not os.path.exists(cfg.results_dir):
break
else:
cfg.run_uuid = str(uuid.uuid4())
cfg.results_dir = os.path.join(results_storage,
cfg.run_uuid)
# setup all files paths
cfg.update(get_test_files(cfg.results_dir))
if existing:
cfg.update(load_run_params(cfg.run_params_file))
testnode_log_root = cfg.get('testnode_log_root')
testnode_log_dir = os.path.join(testnode_log_root, "{0}/{{name}}")
cfg.default_test_local_folder = testnode_log_dir.format(cfg.run_uuid)
return cfg
def save_run_params(cfg):
params = {
'comment': cfg.comment,
'run_uuid': cfg.run_uuid
}
with open(cfg.run_params_file, 'w') as fd:
fd.write(pretty_yaml.dumps(params))
def load_run_params(run_params_file):
with open(run_params_file) as fd:
dt = yaml.load(fd)
return dict(run_uuid=dt['run_uuid'],
comment=dt.get('comment'))
def color_me(color):
RESET_SEQ = "\033[0m"
COLOR_SEQ = "\033[1;%dm"
color_seq = COLOR_SEQ % (30 + color)
def closure(msg):
return color_seq + msg + RESET_SEQ
return closure
class ColoredFormatter(logging.Formatter):
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
colors = {
'WARNING': color_me(YELLOW),
'DEBUG': color_me(BLUE),
'CRITICAL': color_me(YELLOW),
'ERROR': color_me(RED)
}
def __init__(self, msg, use_color=True, datefmt=None):
logging.Formatter.__init__(self, msg, datefmt=datefmt)
self.use_color = use_color
def format(self, record):
orig = record.__dict__
record.__dict__ = record.__dict__.copy()
levelname = record.levelname
prn_name = levelname + ' ' * (8 - len(levelname))
if levelname in self.colors:
record.levelname = self.colors[levelname](prn_name)
else:
record.levelname = prn_name
# super doesn't work here in 2.6 O_o
res = logging.Formatter.format(self, record)
# res = super(ColoredFormatter, self).format(record)
# restore record, as it will be used by other formatters
record.__dict__ = orig
return res
def setup_loggers(def_level=logging.DEBUG, log_fname=None):
logger = logging.getLogger('wally')
logger.setLevel(logging.DEBUG)
sh = logging.StreamHandler()
sh.setLevel(def_level)
log_format = '%(asctime)s - %(levelname)s - %(name)-15s - %(message)s'
colored_formatter = ColoredFormatter(log_format, datefmt="%H:%M:%S")
sh.setFormatter(colored_formatter)
logger.addHandler(sh)
logger_api = logging.getLogger("wally.fuel_api")
if log_fname is not None:
fh = logging.FileHandler(log_fname)
log_format = '%(asctime)s - %(levelname)8s - %(name)-15s - %(message)s'
formatter = logging.Formatter(log_format, datefmt="%H:%M:%S")
fh.setFormatter(formatter)
fh.setLevel(logging.DEBUG)
logger.addHandler(fh)
logger_api.addHandler(fh)
else:
fh = None
logger_api.addHandler(sh)
logger_api.setLevel(logging.WARNING)
logger = logging.getLogger('paramiko')
logger.setLevel(logging.WARNING)
# logger.addHandler(sh)
if fh is not None:
logger.addHandler(fh)