blob: abc6bb0aa1406603c4862e7dbaedef72b363ca25 [file] [log] [blame]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +03001import os
2import uuid
3import logging
4import functools
5
6import yaml
7
8try:
9 from petname import Generate as pet_generate
10except ImportError:
11 def pet_generate(x, y):
12 return str(uuid.uuid4())
13
koder aka kdanilov88407ff2015-05-26 15:35:57 +030014import pretty_yaml
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030015
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030016
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +030017class NoData(object):
18 @classmethod
19 def get(cls, name, x):
20 return cls
21
22
23class Config(object):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030024 def __init__(self, val=None):
25 if val is not None:
26 self.update(val)
27
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +030028 def get(self, name, defval=None):
29 obj = self.__dict__
30 for cname in name.split("."):
31 obj = obj.get(cname, NoData)
32
33 if obj is NoData:
34 return defval
35 return obj
36
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030037 def update(self, val):
38 self.__dict__.update(val)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030039
40
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +030041def get_test_files(results_dir):
42 in_var_dir = functools.partial(os.path.join, results_dir)
43
44 res = dict(
45 run_params_file='run_params.yaml',
46 saved_config_file='config.yaml',
47 vm_ids_fname='os_vm_ids',
48 html_report_file='{0}_report.html',
koder aka kdanilov88407ff2015-05-26 15:35:57 +030049 load_report_file='load_report.html',
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +030050 text_report_file='report.txt',
51 log_file='log.txt',
52 sensor_storage='sensor_storage',
53 nodes_report_file='nodes.yaml',
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030054 results_storage='results',
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +030055 hwinfo_directory='hwinfo',
56 hwreport_fname='hwinfo.txt',
57 raw_results='raw_results.yaml')
58
59 res = dict((k, in_var_dir(v)) for k, v in res.items())
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030060 res['results_dir'] = results_dir
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +030061 return res
62
63
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030064def load_config(file_name):
65 file_name = os.path.abspath(file_name)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030066
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030067 defaults = dict(
68 sensors_remote_path='/tmp/sensors',
69 testnode_log_root='/tmp/wally',
70 settings={}
71 )
koder aka kdanilov88407ff2015-05-26 15:35:57 +030072
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030073 raw_cfg = yaml.load(open(file_name).read())
74 raw_cfg['config_folder'] = os.path.dirname(file_name)
75 if 'include' in raw_cfg:
76 default_path = os.path.join(raw_cfg['config_folder'],
77 raw_cfg.pop('include'))
78 default_cfg = yaml.load(open(default_path).read())
79
80 # TODO: Need more intelectual configs merge?
81 default_cfg.update(raw_cfg)
82 raw_cfg = default_cfg
83
84 cfg = Config(defaults)
85 cfg.update(raw_cfg)
86
87 results_storage = cfg.settings.get('results_storage', '/tmp')
88 results_storage = os.path.abspath(results_storage)
89
90 existing = file_name.startswith(results_storage)
91
92 if existing:
93 cfg.results_dir = os.path.dirname(file_name)
94 cfg.run_uuid = os.path.basename(cfg.results_dir)
95 else:
96 # genarate result folder name
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030097 for i in range(10):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030098 cfg.run_uuid = pet_generate(2, "_")
99 cfg.results_dir = os.path.join(results_storage,
100 cfg.run_uuid)
101 if not os.path.exists(cfg.results_dir):
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300102 break
103 else:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300104 cfg.run_uuid = str(uuid.uuid4())
105 cfg.results_dir = os.path.join(results_storage,
106 cfg.run_uuid)
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300107
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300108 # setup all files paths
109 cfg.update(get_test_files(cfg.results_dir))
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300110
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300111 if existing:
112 cfg.update(load_run_params(cfg.run_params_file))
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300113
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300114 testnode_log_root = cfg.get('testnode_log_root')
koder aka kdanilovafd98742015-04-24 01:27:22 +0300115 testnode_log_dir = os.path.join(testnode_log_root, "{0}/{{name}}")
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300116 cfg.default_test_local_folder = testnode_log_dir.format(cfg.run_uuid)
koder aka kdanilov2066daf2015-04-23 21:05:41 +0300117
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300118 return cfg
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300119
120
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300121def save_run_params(cfg):
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300122 params = {
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300123 'comment': cfg.comment,
124 'run_uuid': cfg.run_uuid
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300125 }
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300126
127 with open(cfg.run_params_file, 'w') as fd:
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300128 fd.write(pretty_yaml.dumps(params))
129
130
131def load_run_params(run_params_file):
132 with open(run_params_file) as fd:
133 dt = yaml.load(fd)
134
135 return dict(run_uuid=dt['run_uuid'],
136 comment=dt.get('comment'))
137
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300138
139def color_me(color):
140 RESET_SEQ = "\033[0m"
141 COLOR_SEQ = "\033[1;%dm"
142
143 color_seq = COLOR_SEQ % (30 + color)
144
145 def closure(msg):
146 return color_seq + msg + RESET_SEQ
147 return closure
148
149
150class ColoredFormatter(logging.Formatter):
151 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
152
153 colors = {
154 'WARNING': color_me(YELLOW),
155 'DEBUG': color_me(BLUE),
156 'CRITICAL': color_me(YELLOW),
157 'ERROR': color_me(RED)
158 }
159
160 def __init__(self, msg, use_color=True, datefmt=None):
161 logging.Formatter.__init__(self, msg, datefmt=datefmt)
162 self.use_color = use_color
163
164 def format(self, record):
165 orig = record.__dict__
166 record.__dict__ = record.__dict__.copy()
167 levelname = record.levelname
168
169 prn_name = levelname + ' ' * (8 - len(levelname))
170 if levelname in self.colors:
171 record.levelname = self.colors[levelname](prn_name)
172 else:
173 record.levelname = prn_name
174
koder aka kdanilov6b1341a2015-04-21 22:44:21 +0300175 # super doesn't work here in 2.6 O_o
176 res = logging.Formatter.format(self, record)
177
178 # res = super(ColoredFormatter, self).format(record)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300179
180 # restore record, as it will be used by other formatters
181 record.__dict__ = orig
182 return res
183
184
185def setup_loggers(def_level=logging.DEBUG, log_fname=None):
186 logger = logging.getLogger('wally')
187 logger.setLevel(logging.DEBUG)
188 sh = logging.StreamHandler()
189 sh.setLevel(def_level)
190
koder aka kdanilov168f6092015-04-19 02:33:38 +0300191 log_format = '%(asctime)s - %(levelname)s - %(name)-15s - %(message)s'
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300192 colored_formatter = ColoredFormatter(log_format, datefmt="%H:%M:%S")
193
194 sh.setFormatter(colored_formatter)
195 logger.addHandler(sh)
196
197 logger_api = logging.getLogger("wally.fuel_api")
198
199 if log_fname is not None:
200 fh = logging.FileHandler(log_fname)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300201 log_format = '%(asctime)s - %(levelname)8s - %(name)-15s - %(message)s'
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300202 formatter = logging.Formatter(log_format, datefmt="%H:%M:%S")
203 fh.setFormatter(formatter)
204 fh.setLevel(logging.DEBUG)
205 logger.addHandler(fh)
206 logger_api.addHandler(fh)
koder aka kdanilovec1b9732015-04-23 20:43:29 +0300207 else:
208 fh = None
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300209
210 logger_api.addHandler(sh)
211 logger_api.setLevel(logging.WARNING)
koder aka kdanilovec1b9732015-04-23 20:43:29 +0300212
213 logger = logging.getLogger('paramiko')
214 logger.setLevel(logging.WARNING)
koder aka kdanilovafd98742015-04-24 01:27:22 +0300215 # logger.addHandler(sh)
koder aka kdanilovec1b9732015-04-23 20:43:29 +0300216 if fh is not None:
217 logger.addHandler(fh)