blob: 332dc5ee0dfbc0004cc2da8b4c356081cf965897 [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')
koder aka kdanilov49977e12016-10-13 22:54:24 +030088 print results_storage
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030089 results_storage = os.path.abspath(results_storage)
90
91 existing = file_name.startswith(results_storage)
92
93 if existing:
94 cfg.results_dir = os.path.dirname(file_name)
95 cfg.run_uuid = os.path.basename(cfg.results_dir)
96 else:
97 # genarate result folder name
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030098 for i in range(10):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030099 cfg.run_uuid = pet_generate(2, "_")
100 cfg.results_dir = os.path.join(results_storage,
101 cfg.run_uuid)
102 if not os.path.exists(cfg.results_dir):
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300103 break
104 else:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300105 cfg.run_uuid = str(uuid.uuid4())
106 cfg.results_dir = os.path.join(results_storage,
107 cfg.run_uuid)
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300108
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300109 # setup all files paths
110 cfg.update(get_test_files(cfg.results_dir))
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300111
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300112 if existing:
113 cfg.update(load_run_params(cfg.run_params_file))
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300114
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300115 testnode_log_root = cfg.get('testnode_log_root')
koder aka kdanilovafd98742015-04-24 01:27:22 +0300116 testnode_log_dir = os.path.join(testnode_log_root, "{0}/{{name}}")
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300117 cfg.default_test_local_folder = testnode_log_dir.format(cfg.run_uuid)
koder aka kdanilov2066daf2015-04-23 21:05:41 +0300118
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300119 return cfg
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300120
121
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300122def save_run_params(cfg):
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300123 params = {
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300124 'comment': cfg.comment,
125 'run_uuid': cfg.run_uuid
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300126 }
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300127
128 with open(cfg.run_params_file, 'w') as fd:
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300129 fd.write(pretty_yaml.dumps(params))
130
131
132def load_run_params(run_params_file):
133 with open(run_params_file) as fd:
134 dt = yaml.load(fd)
135
136 return dict(run_uuid=dt['run_uuid'],
137 comment=dt.get('comment'))
138
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300139
140def color_me(color):
141 RESET_SEQ = "\033[0m"
142 COLOR_SEQ = "\033[1;%dm"
143
144 color_seq = COLOR_SEQ % (30 + color)
145
146 def closure(msg):
147 return color_seq + msg + RESET_SEQ
148 return closure
149
150
151class ColoredFormatter(logging.Formatter):
152 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
153
154 colors = {
155 'WARNING': color_me(YELLOW),
156 'DEBUG': color_me(BLUE),
157 'CRITICAL': color_me(YELLOW),
158 'ERROR': color_me(RED)
159 }
160
161 def __init__(self, msg, use_color=True, datefmt=None):
162 logging.Formatter.__init__(self, msg, datefmt=datefmt)
163 self.use_color = use_color
164
165 def format(self, record):
166 orig = record.__dict__
167 record.__dict__ = record.__dict__.copy()
168 levelname = record.levelname
169
170 prn_name = levelname + ' ' * (8 - len(levelname))
171 if levelname in self.colors:
172 record.levelname = self.colors[levelname](prn_name)
173 else:
174 record.levelname = prn_name
175
koder aka kdanilov6b1341a2015-04-21 22:44:21 +0300176 # super doesn't work here in 2.6 O_o
177 res = logging.Formatter.format(self, record)
178
179 # res = super(ColoredFormatter, self).format(record)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300180
181 # restore record, as it will be used by other formatters
182 record.__dict__ = orig
183 return res
184
185
186def setup_loggers(def_level=logging.DEBUG, log_fname=None):
187 logger = logging.getLogger('wally')
188 logger.setLevel(logging.DEBUG)
189 sh = logging.StreamHandler()
190 sh.setLevel(def_level)
191
koder aka kdanilov168f6092015-04-19 02:33:38 +0300192 log_format = '%(asctime)s - %(levelname)s - %(name)-15s - %(message)s'
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300193 colored_formatter = ColoredFormatter(log_format, datefmt="%H:%M:%S")
194
195 sh.setFormatter(colored_formatter)
196 logger.addHandler(sh)
197
198 logger_api = logging.getLogger("wally.fuel_api")
199
200 if log_fname is not None:
201 fh = logging.FileHandler(log_fname)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300202 log_format = '%(asctime)s - %(levelname)8s - %(name)-15s - %(message)s'
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300203 formatter = logging.Formatter(log_format, datefmt="%H:%M:%S")
204 fh.setFormatter(formatter)
205 fh.setLevel(logging.DEBUG)
206 logger.addHandler(fh)
207 logger_api.addHandler(fh)
koder aka kdanilovec1b9732015-04-23 20:43:29 +0300208 else:
209 fh = None
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300210
211 logger_api.addHandler(sh)
212 logger_api.setLevel(logging.WARNING)
koder aka kdanilovec1b9732015-04-23 20:43:29 +0300213
214 logger = logging.getLogger('paramiko')
215 logger.setLevel(logging.WARNING)
koder aka kdanilovafd98742015-04-24 01:27:22 +0300216 # logger.addHandler(sh)
koder aka kdanilovec1b9732015-04-23 20:43:29 +0300217 if fh is not None:
218 logger.addHandler(fh)