blob: 6bfad3f74df197a913c784f7bdc65416f769d90d [file] [log] [blame]
gstepanov023c1e42015-04-08 15:50:19 +03001import os
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08002import sys
koder aka kdanilov2c473092015-03-29 17:12:13 +03003import Queue
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08004import pprint
koder aka kdanilove21d7472015-02-14 19:02:04 -08005import logging
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08006import argparse
koder aka kdanilov2c473092015-03-29 17:12:13 +03007import threading
8import collections
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08009
koder aka kdanilov66839a92015-04-11 13:22:31 +030010import yaml
koder aka kdanilov2c473092015-03-29 17:12:13 +030011from concurrent.futures import ThreadPoolExecutor
koder aka kdanilov6c491062015-04-09 22:33:13 +030012
koder aka kdanilov2c473092015-03-29 17:12:13 +030013import utils
koder aka kdanilov66839a92015-04-11 13:22:31 +030014import report
koder aka kdanilove06762a2015-03-22 23:32:09 +020015import ssh_utils
koder aka kdanilovda45e882015-04-06 02:24:42 +030016import start_vms
koder aka kdanilov66839a92015-04-11 13:22:31 +030017import pretty_yaml
koder aka kdanilove06762a2015-03-22 23:32:09 +020018from nodes import discover
koder aka kdanilov2c473092015-03-29 17:12:13 +030019from nodes.node import Node
koder aka kdanilov66839a92015-04-11 13:22:31 +030020from config import cfg_dict, load_config
koder aka kdanilov2c473092015-03-29 17:12:13 +030021from sensors.api import start_monitoring
koder aka kdanilov652cd802015-04-13 12:21:07 +030022from tests.itest import IOPerfTest, PgBenchTest
koder aka kdanilov66839a92015-04-11 13:22:31 +030023from formatters import format_results_for_console
koder aka kdanilov2c473092015-03-29 17:12:13 +030024
25
koder aka kdanilove21d7472015-02-14 19:02:04 -080026logger = logging.getLogger("io-perf-tool")
koder aka kdanilove21d7472015-02-14 19:02:04 -080027
28
koder aka kdanilov652cd802015-04-13 12:21:07 +030029def color_me(color):
30 RESET_SEQ = "\033[0m"
31 COLOR_SEQ = "\033[1;%dm"
32
33 color_seq = COLOR_SEQ % (30 + color)
34
35 def closure(msg):
36 return color_seq + msg + RESET_SEQ
37 return closure
38
39
40class ColoredFormatter(logging.Formatter):
41 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
42
43 colors = {
44 'WARNING': color_me(YELLOW),
45 'DEBUG': color_me(BLUE),
46 'CRITICAL': color_me(YELLOW),
47 'ERROR': color_me(RED)
48 }
49
50 def __init__(self, msg, use_color=True):
51 logging.Formatter.__init__(self, msg)
52 self.use_color = use_color
53
54 def format(self, record):
55 levelname = record.levelname
56
57 if levelname in self.colors:
58 record.levelname = self.colors[levelname](levelname)
59
60 return logging.Formatter.format(self, record)
61
62
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030063def setup_logger(logger, level=logging.DEBUG, log_fname=None):
koder aka kdanilov652cd802015-04-13 12:21:07 +030064 logger.setLevel(logging.DEBUG)
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030065 sh = logging.StreamHandler()
66 sh.setLevel(level)
Yulia Portnova7ddfa732015-02-24 17:32:58 +020067
koder aka kdanilov2c473092015-03-29 17:12:13 +030068 log_format = '%(asctime)s - %(levelname)-6s - %(name)s - %(message)s'
koder aka kdanilov652cd802015-04-13 12:21:07 +030069 colored_formatter = ColoredFormatter(log_format,
70 "%H:%M:%S")
71
koder aka kdanilov2c473092015-03-29 17:12:13 +030072 formatter = logging.Formatter(log_format,
73 "%H:%M:%S")
koder aka kdanilov652cd802015-04-13 12:21:07 +030074 sh.setFormatter(colored_formatter)
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030075 logger.addHandler(sh)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080076
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030077 if log_fname is not None:
78 fh = logging.FileHandler(log_fname)
koder aka kdanilov652cd802015-04-13 12:21:07 +030079 fh.setFormatter(formatter)
koder aka kdanilovf4b82c22015-04-11 13:35:25 +030080 fh.setLevel(logging.DEBUG)
81 logger.addHandler(fh)
koder aka kdanilov6c491062015-04-09 22:33:13 +030082
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080083
Yulia Portnova7ddfa732015-02-24 17:32:58 +020084def format_result(res, formatter):
koder aka kdanilove21d7472015-02-14 19:02:04 -080085 data = "\n{0}\n".format("=" * 80)
86 data += pprint.pformat(res) + "\n"
87 data += "{0}\n".format("=" * 80)
koder aka kdanilovfe056622015-02-19 08:46:15 -080088 templ = "{0}\n\n====> {1}\n\n{2}\n\n"
Yulia Portnova7ddfa732015-02-24 17:32:58 +020089 return templ.format(data, formatter(res), "=" * 80)
koder aka kdanilove21d7472015-02-14 19:02:04 -080090
91
koder aka kdanilov1c2b5112015-04-10 16:53:51 +030092class Context(object):
93 def __init__(self):
94 self.build_meta = {}
95 self.nodes = []
96 self.clear_calls_stack = []
97 self.openstack_nodes_ids = []
98
99
koder aka kdanilov5d589b42015-03-26 12:25:51 +0200100def connect_one(node):
101 try:
koder aka kdanilov2c473092015-03-29 17:12:13 +0300102 ssh_pref = "ssh://"
103 if node.conn_url.startswith(ssh_pref):
104 url = node.conn_url[len(ssh_pref):]
105 node.connection = ssh_utils.connect(url)
106 else:
107 raise ValueError("Unknown url type {0}".format(node.conn_url))
koder aka kdanilov3a6633e2015-03-26 18:20:00 +0200108 except Exception:
koder aka kdanilov2c473092015-03-29 17:12:13 +0300109 logger.exception("During connect to {0}".format(node))
koder aka kdanilov652cd802015-04-13 12:21:07 +0300110 raise
koder aka kdanilov5d589b42015-03-26 12:25:51 +0200111
112
113def connect_all(nodes):
koder aka kdanilov2c473092015-03-29 17:12:13 +0300114 logger.info("Connecting to nodes")
115 with ThreadPoolExecutor(32) as pool:
116 list(pool.map(connect_one, nodes))
koder aka kdanilovda45e882015-04-06 02:24:42 +0300117 logger.info("All nodes connected successfully")
koder aka kdanilov2c473092015-03-29 17:12:13 +0300118
119
120def save_sensors_data(q):
121 logger.info("Start receiving sensors data")
koder aka kdanilovda45e882015-04-06 02:24:42 +0300122 sensor_data = []
koder aka kdanilov2c473092015-03-29 17:12:13 +0300123 while True:
124 val = q.get()
125 if val is None:
koder aka kdanilovda45e882015-04-06 02:24:42 +0300126 q.put(sensor_data)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300127 break
koder aka kdanilovda45e882015-04-06 02:24:42 +0300128 sensor_data.append(val)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300129 logger.info("Sensors thread exits")
130
131
koder aka kdanilov652cd802015-04-13 12:21:07 +0300132def test_thread(test, node, barrier, res_q):
koder aka kdanilov2c473092015-03-29 17:12:13 +0300133 try:
134 logger.debug("Run preparation for {0}".format(node.conn_url))
135 test.pre_run(node.connection)
136 logger.debug("Run test for {0}".format(node.conn_url))
137 test.run(node.connection, barrier)
koder aka kdanilov652cd802015-04-13 12:21:07 +0300138 except Exception as exc:
koder aka kdanilov2c473092015-03-29 17:12:13 +0300139 logger.exception("In test {0} for node {1}".format(test, node))
koder aka kdanilov652cd802015-04-13 12:21:07 +0300140 res_q.put(exc)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300141
142
143def run_tests(config, nodes):
144 tool_type_mapper = {
145 "io": IOPerfTest,
146 "pgbench": PgBenchTest,
147 }
148
149 test_nodes = [node for node in nodes
150 if 'testnode' in node.roles]
151
152 res_q = Queue.Queue()
153
koder aka kdanilov652cd802015-04-13 12:21:07 +0300154 for test_block in config:
155 for name, params in test_block.items():
156 logger.info("Starting {0} tests".format(name))
koder aka kdanilov2c473092015-03-29 17:12:13 +0300157
koder aka kdanilov652cd802015-04-13 12:21:07 +0300158 threads = []
159 barrier = utils.Barrier(len(test_nodes))
160 for node in test_nodes:
161 msg = "Starting {0} test on {1} node"
162 logger.debug(msg.format(name, node.conn_url))
163 test = tool_type_mapper[name](params, res_q.put)
164 th = threading.Thread(None, test_thread, None,
165 (test, node, barrier, res_q))
166 threads.append(th)
167 th.daemon = True
168 th.start()
koder aka kdanilov2c473092015-03-29 17:12:13 +0300169
koder aka kdanilov652cd802015-04-13 12:21:07 +0300170 def gather_results(res_q, results):
gstepanov023c1e42015-04-08 15:50:19 +0300171 while not res_q.empty():
koder aka kdanilov652cd802015-04-13 12:21:07 +0300172 val = res_q.get()
koder aka kdanilov66839a92015-04-11 13:22:31 +0300173
koder aka kdanilov652cd802015-04-13 12:21:07 +0300174 if isinstance(val, Exception):
175 msg = "Exception during test execution: {0}"
176 raise ValueError(msg.format(val.message))
177
178 results.append(val)
179
180 results = []
181
182 while True:
183 for th in threads:
184 th.join(1)
185 gather_results(res_q, results)
186
187 if all(not th.is_alive() for th in threads):
188 break
189
190 gather_results(res_q, results)
191 yield name, test.merge_results(results)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300192
193
194def parse_args(argv):
195 parser = argparse.ArgumentParser(
196 description="Run disk io performance test")
197
198 parser.add_argument("-l", dest='extra_logs',
199 action='store_true', default=False,
200 help="print some extra log info")
201
gstepanov4861d712015-04-09 13:28:02 +0300202 parser.add_argument("-b", '--build_description',
203 type=str, default="Build info")
gstepanovaffcdb12015-04-07 17:18:29 +0300204 parser.add_argument("-i", '--build_id', type=str, default="id")
205 parser.add_argument("-t", '--build_type', type=str, default="GA")
206 parser.add_argument("-u", '--username', type=str, default="admin")
koder aka kdanilov66839a92015-04-11 13:22:31 +0300207 parser.add_argument("-p", '--post-process-only', default=None)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300208 parser.add_argument("-o", '--output-dest', nargs="*")
209 parser.add_argument("config_file", nargs="?", default="config.yaml")
koder aka kdanilov2c473092015-03-29 17:12:13 +0300210
211 return parser.parse_args(argv[1:])
212
213
koder aka kdanilovda45e882015-04-06 02:24:42 +0300214def log_nodes_statistic(_, ctx):
215 nodes = ctx.nodes
koder aka kdanilov2c473092015-03-29 17:12:13 +0300216 logger.info("Found {0} nodes total".format(len(nodes)))
217 per_role = collections.defaultdict(lambda: 0)
218 for node in nodes:
219 for role in node.roles:
220 per_role[role] += 1
221
222 for role, count in sorted(per_role.items()):
223 logger.debug("Found {0} nodes with role {1}".format(count, role))
224
225
226def log_sensors_config(cfg):
koder aka kdanilov5d589b42015-03-26 12:25:51 +0200227 pass
228
229
koder aka kdanilovda45e882015-04-06 02:24:42 +0300230def connect_stage(cfg, ctx):
231 ctx.clear_calls_stack.append(disconnect_stage)
232 connect_all(ctx.nodes)
233
234
235def discover_stage(cfg, ctx):
koder aka kdanilov652cd802015-04-13 12:21:07 +0300236 if cfg.get('discover') is not None:
koder aka kdanilovda45e882015-04-06 02:24:42 +0300237 discover_objs = [i.strip() for i in cfg['discover'].strip().split(",")]
238 ctx.nodes.extend(discover.discover(discover_objs, cfg['clouds']))
239
240 for url, roles in cfg.get('explicit_nodes', {}).items():
241 ctx.nodes.append(Node(url, roles.split(",")))
242
243
244def deploy_sensors_stage(cfg_dict, ctx):
koder aka kdanilovda45e882015-04-06 02:24:42 +0300245 if 'sensors' not in cfg_dict:
246 return
247
koder aka kdanilov652cd802015-04-13 12:21:07 +0300248 ctx.clear_calls_stack.append(remove_sensors_stage)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300249 cfg = cfg_dict.get('sensors')
250 sens_cfg = []
251
252 for role, sensors_str in cfg["roles_mapping"].items():
253 sensors = [sens.strip() for sens in sensors_str.split(",")]
254
255 collect_cfg = dict((sensor, {}) for sensor in sensors)
256
257 for node in ctx.nodes:
258 if role in node.roles:
259 sens_cfg.append((node.connection, collect_cfg))
260
261 log_sensors_config(sens_cfg)
262
263 ctx.sensor_cm = start_monitoring(cfg["receiver_uri"], None,
264 connected_config=sens_cfg)
265
266 ctx.sensors_control_queue = ctx.sensor_cm.__enter__()
267
268 th = threading.Thread(None, save_sensors_data, None,
269 (ctx.sensors_control_queue,))
270 th.daemon = True
271 th.start()
272 ctx.sensor_listen_thread = th
273
274
275def remove_sensors_stage(cfg, ctx):
276 ctx.sensors_control_queue.put(None)
277 ctx.sensor_listen_thread.join()
278 ctx.sensor_data = ctx.sensors_control_queue.get()
279
280
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300281def run_all_test(cfg, ctx):
koder aka kdanilovda45e882015-04-06 02:24:42 +0300282 ctx.results = []
283
gstepanov023c1e42015-04-08 15:50:19 +0300284 if 'start_test_nodes' in cfg['tests']:
285 params = cfg['tests']['start_test_nodes']['openstack']
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300286 os_nodes_ids = []
koder aka kdanilov6c491062015-04-09 22:33:13 +0300287
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300288 os_creds = params['creds']
289
290 if os_creds == 'fuel':
291 raise NotImplementedError()
292
293 elif os_creds == 'clouds':
294 os_cfg = cfg['clouds']['openstack']
295 tenant = os_cfg['OS_TENANT_NAME'].strip()
296 user = os_cfg['OS_USERNAME'].strip()
297 passwd = os_cfg['OS_PASSWORD'].strip()
298 auth_url = os_cfg['OS_AUTH_URL'].strip()
299
300 elif os_creds == 'ENV':
301 tenant = None
302 user = None
303 passwd = None
304 auth_url = None
305
306 else:
307 raise ValueError("Only 'ENV' creds are supported")
308
309 start_vms.nova_connect(user, passwd, tenant, auth_url)
310
koder aka kdanilov4e9f3ed2015-04-14 11:26:12 +0300311 logger.info("Preparing openstack")
312 start_vms.prepare_os(user, passwd, tenant, auth_url)
313
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300314 new_nodes = []
315 for new_node, node_id in start_vms.launch_vms(params):
316 new_node.roles.append('testnode')
317 ctx.nodes.append(new_node)
318 os_nodes_ids.append(node_id)
319 new_nodes.append(new_node)
320
koder aka kdanilov66839a92015-04-11 13:22:31 +0300321 store_nodes_in_log(cfg, os_nodes_ids)
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300322 ctx.openstack_nodes_ids = os_nodes_ids
323
324 connect_all(new_nodes)
gstepanov023c1e42015-04-08 15:50:19 +0300325
koder aka kdanilovda45e882015-04-06 02:24:42 +0300326 if 'tests' in cfg:
koder aka kdanilov652cd802015-04-13 12:21:07 +0300327 ctx.results.extend(run_tests(cfg['tests'], ctx.nodes))
koder aka kdanilovda45e882015-04-06 02:24:42 +0300328
gstepanov023c1e42015-04-08 15:50:19 +0300329
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300330def shut_down_vms_stage(cfg, ctx):
koder aka kdanilov66839a92015-04-11 13:22:31 +0300331 vm_ids_fname = cfg_dict['vm_ids_fname']
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300332 if ctx.openstack_nodes_ids is None:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300333 nodes_ids = open(vm_ids_fname).read().split()
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300334 else:
335 nodes_ids = ctx.openstack_nodes_ids
336
koder aka kdanilov652cd802015-04-13 12:21:07 +0300337 if len(nodes_ids) != 0:
338 logger.info("Removing nodes")
339 start_vms.clear_nodes(nodes_ids)
340 logger.info("Nodes has been removed")
gstepanov023c1e42015-04-08 15:50:19 +0300341
koder aka kdanilov66839a92015-04-11 13:22:31 +0300342 if os.path.exists(vm_ids_fname):
343 os.remove(vm_ids_fname)
gstepanov023c1e42015-04-08 15:50:19 +0300344
koder aka kdanilov66839a92015-04-11 13:22:31 +0300345
346def store_nodes_in_log(cfg, nodes_ids):
347 with open(cfg['vm_ids_fname'], 'w') as fd:
348 fd.write("\n".join(nodes_ids))
gstepanov023c1e42015-04-08 15:50:19 +0300349
350
351def clear_enviroment(cfg, ctx):
koder aka kdanilov66839a92015-04-11 13:22:31 +0300352 if os.path.exists(cfg_dict['vm_ids_fname']):
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300353 shut_down_vms_stage(cfg, ctx)
gstepanov023c1e42015-04-08 15:50:19 +0300354
355
356def run_tests_stage(cfg, ctx):
357 # clear nodes that possible were created on previous test running
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300358 # clear_enviroment(cfg, ctx) << fix OS connection
359 ctx.clear_calls_stack.append(shut_down_vms_stage)
360 run_all_test(cfg, ctx)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300361
362
363def disconnect_stage(cfg, ctx):
koder aka kdanilov652cd802015-04-13 12:21:07 +0300364 ssh_utils.close_all_sessions()
365
koder aka kdanilovda45e882015-04-06 02:24:42 +0300366 for node in ctx.nodes:
367 if node.connection is not None:
368 node.connection.close()
369
370
koder aka kdanilov66839a92015-04-11 13:22:31 +0300371def yamable(data):
372 if isinstance(data, (tuple, list)):
373 return map(yamable, data)
374
375 if isinstance(data, unicode):
376 return str(data)
377
378 if isinstance(data, dict):
379 res = {}
380 for k, v in data.items():
381 res[yamable(k)] = yamable(v)
382 return res
383
384 return data
385
386
387def store_raw_results_stage(cfg, ctx):
388
389 raw_results = os.path.join(cfg_dict['var_dir'], 'raw_results.yaml')
390
391 if os.path.exists(raw_results):
392 cont = yaml.load(open(raw_results).read())
393 else:
394 cont = []
395
396 cont.extend(yamable(ctx.results))
397 raw_data = pretty_yaml.dumps(cont)
398
399 with open(raw_results, "w") as fd:
400 fd.write(raw_data)
401
402
403def console_report_stage(cfg, ctx):
404 for tp, data in ctx.results:
405 if 'io' == tp:
406 print format_results_for_console(data)
407
408
koder aka kdanilovda45e882015-04-06 02:24:42 +0300409def report_stage(cfg, ctx):
koder aka kdanilov652cd802015-04-13 12:21:07 +0300410 # html_report = report.make_io_report(ctx.results)
411 # html_rep_fname = cfg['html_report_file']
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300412
koder aka kdanilov652cd802015-04-13 12:21:07 +0300413 # with open(html_rep_fname, "w") as fd:
414 # fd.write(html_report)
415
416 # logger.info("Html report were stored in " + html_rep_fname)
417
418 text_rep_fname = cfg_dict['text_report_file']
419 with open(text_rep_fname, "w") as fd:
420 for tp, data in ctx.results:
421 if 'io' == tp:
422 fd.write(format_results_for_console(data))
423 fd.write("\n")
424 fd.flush()
425
426 logger.info("Text report were stored in " + text_rep_fname)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300427
428
429def complete_log_nodes_statistic(cfg, ctx):
430 nodes = ctx.nodes
431 for node in nodes:
432 logger.debug(str(node))
433
434
koder aka kdanilov66839a92015-04-11 13:22:31 +0300435def load_data_from(var_dir):
koder aka kdanilov4e9f3ed2015-04-14 11:26:12 +0300436 def load_data_from_file(cfg, ctx):
koder aka kdanilov66839a92015-04-11 13:22:31 +0300437 raw_results = os.path.join(var_dir, 'raw_results.yaml')
koder aka kdanilov4e9f3ed2015-04-14 11:26:12 +0300438 print "load data from", raw_results
koder aka kdanilov66839a92015-04-11 13:22:31 +0300439 ctx.results = yaml.load(open(raw_results).read())
koder aka kdanilov4e9f3ed2015-04-14 11:26:12 +0300440 return load_data_from_file
gstepanovcd256d62015-04-07 17:47:32 +0300441
442
koder aka kdanilov3f356262015-02-13 08:06:14 -0800443def main(argv):
koder aka kdanilove06762a2015-03-22 23:32:09 +0200444 opts = parse_args(argv)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300445
koder aka kdanilov66839a92015-04-11 13:22:31 +0300446 if opts.post_process_only is not None:
447 stages = [
448 load_data_from(opts.post_process_only),
449 console_report_stage,
koder aka kdanilov652cd802015-04-13 12:21:07 +0300450 report_stage
koder aka kdanilov66839a92015-04-11 13:22:31 +0300451 ]
452 else:
453 stages = [
454 discover_stage,
455 log_nodes_statistic,
koder aka kdanilov66839a92015-04-11 13:22:31 +0300456 connect_stage,
koder aka kdanilov66839a92015-04-11 13:22:31 +0300457 deploy_sensors_stage,
458 run_tests_stage,
459 store_raw_results_stage,
460 console_report_stage,
461 report_stage
462 ]
463
gstepanovcd256d62015-04-07 17:47:32 +0300464 load_config(opts.config_file)
koder aka kdanilovf4b82c22015-04-11 13:35:25 +0300465
466 level = logging.DEBUG if opts.extra_logs else logging.WARNING
467 setup_logger(logger, level, cfg_dict['log_file'])
468
koder aka kdanilov652cd802015-04-13 12:21:07 +0300469 logger.info("All info would be stored into {0}".format(
470 cfg_dict['var_dir']))
gstepanovcd256d62015-04-07 17:47:32 +0300471
koder aka kdanilovda45e882015-04-06 02:24:42 +0300472 ctx = Context()
gstepanovaffcdb12015-04-07 17:18:29 +0300473 ctx.build_meta['build_id'] = opts.build_id
474 ctx.build_meta['build_descrption'] = opts.build_description
475 ctx.build_meta['build_type'] = opts.build_type
476 ctx.build_meta['username'] = opts.username
koder aka kdanilov6c491062015-04-09 22:33:13 +0300477
koder aka kdanilovda45e882015-04-06 02:24:42 +0300478 try:
479 for stage in stages:
480 logger.info("Start {0.__name__} stage".format(stage))
481 stage(cfg_dict, ctx)
482 finally:
483 exc, cls, tb = sys.exc_info()
484 for stage in ctx.clear_calls_stack[::-1]:
485 try:
486 logger.info("Start {0.__name__} stage".format(stage))
487 stage(cfg_dict, ctx)
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300488 except Exception as exc:
489 logger.exception("During {0.__name__} stage".format(stage))
koder aka kdanilov2c473092015-03-29 17:12:13 +0300490
koder aka kdanilovda45e882015-04-06 02:24:42 +0300491 if exc is not None:
492 raise exc, cls, tb
koder aka kdanilov2c473092015-03-29 17:12:13 +0300493
koder aka kdanilov652cd802015-04-13 12:21:07 +0300494 logger.info("All info stotored into {0}".format(cfg_dict['var_dir']))
koder aka kdanilove06762a2015-03-22 23:32:09 +0200495 return 0
koder aka kdanilov3f356262015-02-13 08:06:14 -0800496
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800497
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -0800498if __name__ == '__main__':
koder aka kdanilove06762a2015-03-22 23:32:09 +0200499 exit(main(sys.argv))