blob: 487fd49636d921c0bbf802c3c47461b6532f48ef [file] [log] [blame]
gstepanov023c1e42015-04-08 15:50:19 +03001import os
koder aka kdanilovbc2c8982015-06-13 02:50:43 +03002import re
koder aka kdanilov57ce4db2015-04-25 21:25:51 +03003import time
koder aka kdanilove21d7472015-02-14 19:02:04 -08004import logging
koder aka kdanilov168f6092015-04-19 02:33:38 +03005import functools
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +03006import contextlib
koder aka kdanilov2c473092015-03-29 17:12:13 +03007import collections
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08008
koder aka kdanilov88407ff2015-05-26 15:35:57 +03009from yaml import load as _yaml_load
10
11try:
12 from yaml import CLoader
13 yaml_load = functools.partial(_yaml_load, Loader=CLoader)
14except ImportError:
15 yaml_load = _yaml_load
16
koder aka kdanilov2c473092015-03-29 17:12:13 +030017from concurrent.futures import ThreadPoolExecutor
koder aka kdanilov6c491062015-04-09 22:33:13 +030018
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030019from wally.hw_info import get_hw_info
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030020from wally.config import get_test_files
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030021from wally.discover import discover, Node
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030022from wally import pretty_yaml, utils, report, ssh_utils, start_vms
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030023from wally.sensors_utils import with_sensors_util, sensors_info_util
24
koder aka kdanilovbc2c8982015-06-13 02:50:43 +030025from wally.suits.mysql import MysqlTest
26from wally.suits.itest import TestConfig
27from wally.suits.io.fio import IOPerfTest
28from wally.suits.postgres import PgBenchTest
29
30
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030031TOOL_TYPE_MAPPER = {
32 "io": IOPerfTest,
33 "pgbench": PgBenchTest,
34 "mysql": MysqlTest,
35}
koder aka kdanilov63ad2062015-04-27 13:11:40 +030036
koder aka kdanilov57ce4db2015-04-25 21:25:51 +030037
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030038logger = logging.getLogger("wally")
koder aka kdanilovcee43342015-04-14 22:52:53 +030039
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080040
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030041def connect_all(nodes, spawned_node=False):
42 """
43 Connect to all nodes, log errors
44 nodes:[Node] - list of nodes
45 spawned_node:bool - whenever nodes is newly spawned VM
46 """
koder aka kdanilove21d7472015-02-14 19:02:04 -080047
koder aka kdanilov2c473092015-03-29 17:12:13 +030048 logger.info("Connecting to nodes")
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030049
50 conn_timeout = 240 if spawned_node else 30
51
52 def connect_ext(conn_url):
53 try:
54 return ssh_utils.connect(conn_url, conn_timeout=conn_timeout)
55 except Exception as exc:
56 logger.error("During connect to {0}: {1!s}".format(conn_url, exc))
57 return None
58
59 urls = []
60 ssh_pref = "ssh://"
61
62 for node in nodes:
63 if node.conn_url == 'local':
64 urls.append(node.conn_url)
65 elif node.conn_url.startswith(ssh_pref):
66 urls.append(node.conn_url[len(ssh_pref):])
67 else:
68 msg = "Unknown url type {0}".format(node.conn_url)
69 logger.error(msg)
70 raise utils.StopTestError(msg)
71
koder aka kdanilov2c473092015-03-29 17:12:13 +030072 with ThreadPoolExecutor(32) as pool:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030073 for node, conn in zip(nodes, pool.map(connect_ext, urls)):
74 node.connection = conn
75
76 failed_testnodes = []
77 failed_nodes = []
78
79 for node in nodes:
80 if node.connection is None:
81 if 'testnode' in node.roles:
82 failed_testnodes.append(node.get_conn_id())
83 else:
84 failed_nodes.append(node.get_conn_id())
85
86 if failed_nodes != []:
87 msg = "Node(s) {0} would be excluded - can't connect"
88 logger.warning(msg.format(",".join(failed_nodes)))
89
90 if failed_testnodes != []:
91 msg = "Can't connect to testnode(s) " + ",".join(failed_testnodes)
92 logger.error(msg)
93 raise utils.StopTestError(msg)
94
95 if len(failed_nodes) == 0:
96 logger.info("All nodes connected successfully")
koder aka kdanilov2c473092015-03-29 17:12:13 +030097
98
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030099def collect_hw_info_stage(cfg, ctx):
100 if os.path.exists(cfg['hwreport_fname']):
101 msg = "{0} already exists. Skip hw info"
102 logger.info(msg.format(cfg['hwreport_fname']))
103 return
104
105 with ThreadPoolExecutor(32) as pool:
106 connections = (node.connection for node in ctx.nodes)
107 ctx.hw_info.extend(pool.map(get_hw_info, connections))
108
109 with open(cfg['hwreport_fname'], 'w') as hwfd:
110 for node, info in zip(ctx.nodes, ctx.hw_info):
111 hwfd.write("-" * 60 + "\n")
112 hwfd.write("Roles : " + ", ".join(node.roles) + "\n")
113 hwfd.write(str(info) + "\n")
114 hwfd.write("-" * 60 + "\n\n")
115
116 if info.hostname is not None:
117 fname = os.path.join(
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300118 cfg.hwinfo_directory,
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300119 info.hostname + "_lshw.xml")
120
121 with open(fname, "w") as fd:
122 fd.write(info.raw)
123 logger.info("Hardware report stored in " + cfg['hwreport_fname'])
124 logger.debug("Raw hardware info in " + cfg['hwinfo_directory'] + " folder")
125
126
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300127@contextlib.contextmanager
128def suspend_vm_nodes_ctx(unused_nodes):
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300129 pausable_nodes_ids = [node.os_vm_id for node in unused_nodes
130 if node.os_vm_id is not None]
131 non_pausable = len(unused_nodes) - len(pausable_nodes_ids)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300132
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300133 if 0 != non_pausable:
134 logger.warning("Can't pause {0} nodes".format(
135 non_pausable))
136
137 if len(pausable_nodes_ids) != 0:
138 logger.debug("Try to pause {0} unused nodes".format(
139 len(pausable_nodes_ids)))
140 start_vms.pause(pausable_nodes_ids)
141
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300142 try:
143 yield pausable_nodes_ids
144 finally:
145 if len(pausable_nodes_ids) != 0:
146 logger.debug("Unpausing {0} nodes".format(
147 len(pausable_nodes_ids)))
148 start_vms.unpause(pausable_nodes_ids)
149
150
151def generate_result_dir_name(results, name, params):
152 # make a directory for results
153 all_tests_dirs = os.listdir(results)
154
155 if 'name' in params:
156 dir_name = "{0}_{1}".format(name, params['name'])
157 else:
158 for idx in range(len(all_tests_dirs) + 1):
159 dir_name = "{0}_{1}".format(name, idx)
160 if dir_name not in all_tests_dirs:
161 break
162 else:
163 raise utils.StopTestError("Can't select directory for test results")
164
165 return os.path.join(results, dir_name)
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300166
167
168def run_tests(cfg, test_block, nodes):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300169 """
170 Run test from test block
171 """
172 test_nodes = [node for node in nodes if 'testnode' in node.roles]
173 not_test_nodes = [node for node in nodes if 'testnode' not in node.roles]
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300174
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300175 if len(test_nodes) == 0:
176 logger.error("No test nodes found")
177 return
178
koder aka kdanilovcee43342015-04-14 22:52:53 +0300179 for name, params in test_block.items():
koder aka kdanilovcee43342015-04-14 22:52:53 +0300180 results = []
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300181
182 # iterate over all node counts
183 limit = params.get('node_limit', len(test_nodes))
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300184 if isinstance(limit, (int, long)):
185 vm_limits = [limit]
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300186 else:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300187 list_or_tpl = isinstance(limit, (tuple, list))
188 all_ints = list_or_tpl and all(isinstance(climit, (int, long))
189 for climit in limit)
190 if not all_ints:
191 msg = "'node_limit' parameter ion config should" + \
192 "be either int or list if integers, not {0!r}".format(limit)
193 raise ValueError(msg)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300194 vm_limits = limit
koder aka kdanilov652cd802015-04-13 12:21:07 +0300195
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300196 for vm_count in vm_limits:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300197 # select test nodes
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300198 if vm_count == 'all':
199 curr_test_nodes = test_nodes
200 unused_nodes = []
201 else:
202 curr_test_nodes = test_nodes[:vm_count]
203 unused_nodes = test_nodes[vm_count:]
koder aka kdanilove87ae652015-04-20 02:14:35 +0300204
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300205 if 0 == len(curr_test_nodes):
206 continue
koder aka kdanilov652cd802015-04-13 12:21:07 +0300207
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300208 results_path = generate_result_dir_name(cfg.results_storage, name, params)
209 utils.mkdirs_if_unxists(results_path)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300210
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300211 # suspend all unused virtual nodes
212 if cfg.settings.get('suspend_unused_vms', True):
213 suspend_ctx = suspend_vm_nodes_ctx(unused_nodes)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300214 else:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300215 suspend_ctx = utils.empty_ctx()
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300216
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300217 with suspend_ctx:
218 resumable_nodes_ids = [node.os_vm_id for node in curr_test_nodes
219 if node.os_vm_id is not None]
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300220
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300221 if len(resumable_nodes_ids) != 0:
222 logger.debug("Check and unpause {0} nodes".format(
223 len(resumable_nodes_ids)))
224 start_vms.unpause(resumable_nodes_ids)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300225
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300226 sens_nodes = curr_test_nodes + not_test_nodes
227 with sensors_info_util(cfg, sens_nodes) as sensor_data:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300228 test_cls = TOOL_TYPE_MAPPER[name]
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300229
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300230 remote_dir = cfg.default_test_local_folder.format(name=name)
231
232 test_cfg = TestConfig(test_cls.__name__,
233 params=params,
234 test_uuid=cfg.run_uuid,
235 nodes=test_nodes,
236 log_directory=results_path,
237 remote_dir=remote_dir)
238
239 t_start = time.time()
240 res = test_cls(test_cfg).run()
241 t_end = time.time()
242
243 # save sensor data
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300244 if sensor_data is not None:
245 fname = "{0}_{1}.csv".format(int(t_start), int(t_end))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300246 fpath = os.path.join(cfg.sensor_storage, fname)
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300247
248 with open(fpath, "w") as fd:
249 fd.write("\n\n".join(sensor_data))
250
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300251 results.append(res)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300252
253 yield name, results
koder aka kdanilov2c473092015-03-29 17:12:13 +0300254
255
koder aka kdanilovda45e882015-04-06 02:24:42 +0300256def connect_stage(cfg, ctx):
257 ctx.clear_calls_stack.append(disconnect_stage)
258 connect_all(ctx.nodes)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300259 ctx.nodes = [node for node in ctx.nodes if node.connection is not None]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300260
261
koder aka kdanilovda45e882015-04-06 02:24:42 +0300262def discover_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300263 """
264 discover clusters and nodes stage
265 """
koder aka kdanilov652cd802015-04-13 12:21:07 +0300266 if cfg.get('discover') is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300267 discover_objs = [i.strip() for i in cfg.discover.strip().split(",")]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300268
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300269 nodes = discover(ctx,
270 discover_objs,
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300271 cfg.clouds,
272 cfg.results_storage,
273 not cfg.dont_discover_nodes)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300274
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300275 ctx.nodes.extend(nodes)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300276
277 for url, roles in cfg.get('explicit_nodes', {}).items():
278 ctx.nodes.append(Node(url, roles.split(",")))
279
280
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300281def save_nodes_stage(cfg, ctx):
282 cluster = {}
283 for node in ctx.nodes:
284 roles = node.roles[:]
285 if 'testnode' in roles:
286 roles.remove('testnode')
287
288 if len(roles) != 0:
289 cluster[node.conn_url] = roles
290
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300291 with open(cfg.nodes_report_file, "w") as fd:
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300292 fd.write(pretty_yaml.dumps(cluster))
293
294
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300295def reuse_vms_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300296 vms_patterns = cfg.get('clouds', {}).get('openstack', {}).get('vms', [])
297 private_key_path = get_vm_keypair(cfg)['keypair_file_private']
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300298
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300299 for creds in vms_patterns:
300 user_name, vm_name_pattern = creds.split("@", 1)
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300301 msg = "Vm like {0} lookup failed".format(vm_name_pattern)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300302
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300303 with utils.log_error(msg):
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300304 msg = "Looking for vm with name like {0}".format(vm_name_pattern)
305 logger.debug(msg)
306
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300307 if not start_vms.is_connected():
308 os_creds = get_OS_credentials(cfg, ctx)
309 else:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300310 os_creds = None
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300311
koder aka kdanilovb7197432015-07-15 00:40:43 +0300312 conn = start_vms.nova_connect(os_creds)
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300313 for ip, vm_id in start_vms.find_vms(conn, vm_name_pattern):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300314 conn_url = "ssh://{user}@{ip}::{key}".format(user=user_name,
315 ip=ip,
316 key=private_key_path)
317 node = Node(conn_url, ['testnode'])
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300318 node.os_vm_id = vm_id
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300319 ctx.nodes.append(node)
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300320
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300321
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300322def get_OS_credentials(cfg, ctx):
koder aka kdanilovcee43342015-04-14 22:52:53 +0300323 creds = None
koder aka kdanilovb7197432015-07-15 00:40:43 +0300324 os_creds = None
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300325
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300326 if 'openstack' in cfg.clouds:
327 os_cfg = cfg.clouds['openstack']
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300328 if 'OPENRC' in os_cfg:
329 logger.info("Using OS credentials from " + os_cfg['OPENRC'])
koder aka kdanilovb7197432015-07-15 00:40:43 +0300330 creds_tuple = utils.get_creds_openrc(os_cfg['OPENRC'])
331 os_creds = start_vms.OSCreds(*creds_tuple)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300332 elif 'ENV' in os_cfg:
333 logger.info("Using OS credentials from shell environment")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300334 os_creds = start_vms.ostack_get_creds()
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300335 elif 'OS_TENANT_NAME' in os_cfg:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300336 logger.info("Using predefined credentials")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300337 os_creds = start_vms.OSCreds(os_cfg['OS_USERNAME'].strip(),
338 os_cfg['OS_PASSWORD'].strip(),
339 os_cfg['OS_TENANT_NAME'].strip(),
340 os_cfg['OS_AUTH_URL'].strip(),
341 os_cfg.get('OS_INSECURE', False))
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300342
koder aka kdanilovb7197432015-07-15 00:40:43 +0300343 if os_creds is None and 'fuel' in cfg.clouds and \
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300344 'openstack_env' in cfg.clouds['fuel'] and \
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300345 ctx.fuel_openstack_creds is not None:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300346 logger.info("Using fuel creds")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300347 creds = start_vms.OSCreds(**ctx.fuel_openstack_creds)
348 elif os_creds is None:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300349 logger.error("Can't found OS credentials")
350 raise utils.StopTestError("Can't found OS credentials", None)
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300351
koder aka kdanilovcee43342015-04-14 22:52:53 +0300352 if creds is None:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300353 creds = os_creds
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300354
koder aka kdanilovb7197432015-07-15 00:40:43 +0300355 logger.debug(("OS_CREDS: user={0.name} tenant={0.tenant}" +
356 "auth_url={0.auth_url} insecure={0.insecure}").format(creds))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300357
koder aka kdanilovcee43342015-04-14 22:52:53 +0300358 return creds
koder aka kdanilov4e9f3ed2015-04-14 11:26:12 +0300359
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300360
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300361def get_vm_keypair(cfg):
362 res = {}
363 for field, ext in (('keypair_file_private', 'pem'),
364 ('keypair_file_public', 'pub')):
365 fpath = cfg.vm_configs.get(field)
366
367 if fpath is None:
368 fpath = cfg.vm_configs['keypair_name'] + "." + ext
369
370 if os.path.isabs(fpath):
371 res[field] = fpath
372 else:
373 res[field] = os.path.join(cfg.config_folder, fpath)
374 return res
375
376
koder aka kdanilov168f6092015-04-19 02:33:38 +0300377@contextlib.contextmanager
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300378def create_vms_ctx(ctx, cfg, config, already_has_count=0):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300379 if config['count'].startswith('='):
380 count = int(config['count'][1:])
381 if count <= already_has_count:
382 logger.debug("Not need new vms")
383 yield []
384 return
385
386 params = cfg.vm_configs[config['cfg_name']].copy()
koder aka kdanilov168f6092015-04-19 02:33:38 +0300387 os_nodes_ids = []
388
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300389 if not start_vms.is_connected():
390 os_creds = get_OS_credentials(cfg, ctx)
391 else:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300392 os_creds = None
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300393
koder aka kdanilovb7197432015-07-15 00:40:43 +0300394 nova = start_vms.nova_connect(os_creds)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300395
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300396 params.update(config)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300397 params.update(get_vm_keypair(cfg))
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300398
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300399 params['group_name'] = cfg.run_uuid
400 params['keypair_name'] = cfg.vm_configs['keypair_name']
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300401
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300402 if not config.get('skip_preparation', False):
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300403 logger.info("Preparing openstack")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300404 start_vms.prepare_os_subpr(nova, params, os_creds)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300405
406 new_nodes = []
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300407 old_nodes = ctx.nodes[:]
koder aka kdanilov168f6092015-04-19 02:33:38 +0300408 try:
koder aka kdanilovbc2c8982015-06-13 02:50:43 +0300409 for new_node, node_id in start_vms.launch_vms(params, already_has_count):
koder aka kdanilov168f6092015-04-19 02:33:38 +0300410 new_node.roles.append('testnode')
411 ctx.nodes.append(new_node)
412 os_nodes_ids.append(node_id)
413 new_nodes.append(new_node)
414
415 store_nodes_in_log(cfg, os_nodes_ids)
416 ctx.openstack_nodes_ids = os_nodes_ids
417
418 yield new_nodes
419
420 finally:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300421 if not cfg.keep_vm:
koder aka kdanilov168f6092015-04-19 02:33:38 +0300422 shut_down_vms_stage(cfg, ctx)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300423 ctx.nodes = old_nodes
koder aka kdanilov168f6092015-04-19 02:33:38 +0300424
425
koder aka kdanilovcee43342015-04-14 22:52:53 +0300426def run_tests_stage(cfg, ctx):
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300427 ctx.results = collections.defaultdict(lambda: [])
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300428
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300429 for group in cfg.get('tests', []):
koder aka kdanilovcee43342015-04-14 22:52:53 +0300430
koder aka kdanilov170936a2015-06-27 22:51:17 +0300431 if len(group.items()) != 1:
432 msg = "Items in tests section should have len == 1"
433 logger.error(msg)
434 raise utils.StopTestError(msg)
435
koder aka kdanilovcee43342015-04-14 22:52:53 +0300436 key, config = group.items()[0]
437
438 if 'start_test_nodes' == key:
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300439 if 'openstack' not in config:
440 msg = "No openstack block in config - can't spawn vm's"
441 logger.error(msg)
442 raise utils.StopTestError(msg)
443
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300444 num_test_nodes = 0
445 for node in ctx.nodes:
446 if 'testnode' in node.roles:
447 num_test_nodes += 1
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300448
449 vm_ctx = create_vms_ctx(ctx, cfg, config['openstack'],
450 num_test_nodes)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300451 tests = config.get('tests', [])
452 else:
453 vm_ctx = utils.empty_ctx([])
454 tests = [group]
koder aka kdanilovcee43342015-04-14 22:52:53 +0300455
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300456 if cfg.get('sensors') is None:
457 sensor_ctx = utils.empty_ctx()
458 else:
459 sensor_ctx = with_sensors_util(cfg.get('sensors'), ctx.nodes)
koder aka kdanilovcee43342015-04-14 22:52:53 +0300460
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300461 with vm_ctx as new_nodes:
462 if len(new_nodes) != 0:
463 connect_all(new_nodes, True)
464
465 if not cfg.no_tests:
466 for test_group in tests:
467 with sensor_ctx:
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300468 for tp, res in run_tests(cfg, test_group, ctx.nodes):
469 ctx.results[tp].extend(res)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300470
gstepanov023c1e42015-04-08 15:50:19 +0300471
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300472def shut_down_vms_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300473 vm_ids_fname = cfg.vm_ids_fname
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300474 if ctx.openstack_nodes_ids is None:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300475 nodes_ids = open(vm_ids_fname).read().split()
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300476 else:
477 nodes_ids = ctx.openstack_nodes_ids
478
koder aka kdanilov652cd802015-04-13 12:21:07 +0300479 if len(nodes_ids) != 0:
480 logger.info("Removing nodes")
481 start_vms.clear_nodes(nodes_ids)
482 logger.info("Nodes has been removed")
gstepanov023c1e42015-04-08 15:50:19 +0300483
koder aka kdanilov66839a92015-04-11 13:22:31 +0300484 if os.path.exists(vm_ids_fname):
485 os.remove(vm_ids_fname)
gstepanov023c1e42015-04-08 15:50:19 +0300486
koder aka kdanilov66839a92015-04-11 13:22:31 +0300487
488def store_nodes_in_log(cfg, nodes_ids):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300489 with open(cfg.vm_ids_fname, 'w') as fd:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300490 fd.write("\n".join(nodes_ids))
gstepanov023c1e42015-04-08 15:50:19 +0300491
492
493def clear_enviroment(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300494 if os.path.exists(cfg.vm_ids_fname):
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300495 shut_down_vms_stage(cfg, ctx)
gstepanov023c1e42015-04-08 15:50:19 +0300496
497
koder aka kdanilovda45e882015-04-06 02:24:42 +0300498def disconnect_stage(cfg, ctx):
koder aka kdanilov652cd802015-04-13 12:21:07 +0300499 ssh_utils.close_all_sessions()
500
koder aka kdanilovda45e882015-04-06 02:24:42 +0300501 for node in ctx.nodes:
502 if node.connection is not None:
503 node.connection.close()
504
505
koder aka kdanilov66839a92015-04-11 13:22:31 +0300506def store_raw_results_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300507 if os.path.exists(cfg.raw_results):
508 cont = yaml_load(open(cfg.raw_results).read())
koder aka kdanilov66839a92015-04-11 13:22:31 +0300509 else:
510 cont = []
511
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300512 cont.extend(utils.yamable(ctx.results).items())
koder aka kdanilov66839a92015-04-11 13:22:31 +0300513 raw_data = pretty_yaml.dumps(cont)
514
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300515 with open(cfg.raw_results, "w") as fd:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300516 fd.write(raw_data)
517
518
519def console_report_stage(cfg, ctx):
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300520 first_report = True
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300521 text_rep_fname = cfg.text_report_file
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300522 with open(text_rep_fname, "w") as fd:
523 for tp, data in ctx.results.items():
524 if 'io' == tp and data is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300525 rep_lst = []
526 for result in data:
527 rep_lst.append(
528 IOPerfTest.format_for_console(list(result)))
529 rep = "\n\n".join(rep_lst)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300530 elif tp in ['mysql', 'pgbench'] and data is not None:
531 rep = MysqlTest.format_for_console(data)
532 else:
533 logger.warning("Can't generate text report for " + tp)
534 continue
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300535
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300536 fd.write(rep)
537 fd.write("\n")
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300538
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300539 if first_report:
540 logger.info("Text report were stored in " + text_rep_fname)
541 first_report = False
542
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300543 print("\n" + rep + "\n")
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300544
koder aka kdanilov66839a92015-04-11 13:22:31 +0300545
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300546def test_load_report_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300547 load_rep_fname = cfg.load_report_file
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300548 found = False
549 for idx, (tp, data) in enumerate(ctx.results.items()):
550 if 'io' == tp and data is not None:
551 if found:
552 logger.error("Making reports for more than one " +
553 "io block isn't supported! All " +
554 "report, except first are skipped")
555 continue
556 found = True
557 report.make_load_report(idx, cfg['results'], load_rep_fname)
558
559
koder aka kdanilove87ae652015-04-20 02:14:35 +0300560def html_report_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300561 html_rep_fname = cfg.html_report_file
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300562 found = False
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300563 for tp, data in ctx.results.items():
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300564 if 'io' == tp and data is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300565 if found or len(data) > 1:
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300566 logger.error("Making reports for more than one " +
567 "io block isn't supported! All " +
568 "report, except first are skipped")
569 continue
570 found = True
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300571 report.make_io_report(list(data[0]),
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300572 cfg.get('comment', ''),
573 html_rep_fname,
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300574 lab_info=ctx.hw_info)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300575
koder aka kdanilovda45e882015-04-06 02:24:42 +0300576
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300577def load_data_from_path(test_res_dir):
578 files = get_test_files(test_res_dir)
579 raw_res = yaml_load(open(files['raw_results']).read())
580 res = collections.defaultdict(lambda: [])
koder aka kdanilovda45e882015-04-06 02:24:42 +0300581
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300582 for tp, test_lists in raw_res:
583 for tests in test_lists:
584 for suite_name, suite_data in tests.items():
585 result_folder = suite_data[0]
586 res[tp].append(TOOL_TYPE_MAPPER[tp].load(suite_name, result_folder))
koder aka kdanilovda45e882015-04-06 02:24:42 +0300587
koder aka kdanilov6b872662015-06-23 01:58:36 +0300588 return res
589
590
591def load_data_from_path_stage(var_dir, _, ctx):
592 for tp, vals in load_data_from_path(var_dir).items():
593 ctx.results.setdefault(tp, []).extend(vals)
koder aka kdanilovbc2c8982015-06-13 02:50:43 +0300594
595
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300596def load_data_from(var_dir):
koder aka kdanilov6b872662015-06-23 01:58:36 +0300597 return functools.partial(load_data_from_path_stage, var_dir)