blob: 2cd397e8e9d4559e27712f8930186c6923f4d7b5 [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 kdanilov8fbb27f2015-07-17 22:23:31 +0300325 force_insecure = False
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300326
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300327 if 'openstack' in cfg.clouds:
328 os_cfg = cfg.clouds['openstack']
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300329 if 'OPENRC' in os_cfg:
330 logger.info("Using OS credentials from " + os_cfg['OPENRC'])
koder aka kdanilovb7197432015-07-15 00:40:43 +0300331 creds_tuple = utils.get_creds_openrc(os_cfg['OPENRC'])
332 os_creds = start_vms.OSCreds(*creds_tuple)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300333 elif 'ENV' in os_cfg:
334 logger.info("Using OS credentials from shell environment")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300335 os_creds = start_vms.ostack_get_creds()
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300336 elif 'OS_TENANT_NAME' in os_cfg:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300337 logger.info("Using predefined credentials")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300338 os_creds = start_vms.OSCreds(os_cfg['OS_USERNAME'].strip(),
339 os_cfg['OS_PASSWORD'].strip(),
340 os_cfg['OS_TENANT_NAME'].strip(),
341 os_cfg['OS_AUTH_URL'].strip(),
342 os_cfg.get('OS_INSECURE', False))
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300343
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300344 elif 'OS_INSECURE' in os_cfg:
345 force_insecure = os_cfg.get('OS_INSECURE', False)
346
koder aka kdanilovb7197432015-07-15 00:40:43 +0300347 if os_creds is None and 'fuel' in cfg.clouds and \
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300348 'openstack_env' in cfg.clouds['fuel'] and \
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300349 ctx.fuel_openstack_creds is not None:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300350 logger.info("Using fuel creds")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300351 creds = start_vms.OSCreds(**ctx.fuel_openstack_creds)
352 elif os_creds is None:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300353 logger.error("Can't found OS credentials")
354 raise utils.StopTestError("Can't found OS credentials", None)
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300355
koder aka kdanilovcee43342015-04-14 22:52:53 +0300356 if creds is None:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300357 creds = os_creds
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300358
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300359 if force_insecure and not creds.insecure:
360 creds = start_vms.OSCreds(creds.name,
361 creds.passwd,
362 creds.tenant,
363 creds.auth_url,
364 True)
365
koder aka kdanilovb7197432015-07-15 00:40:43 +0300366 logger.debug(("OS_CREDS: user={0.name} tenant={0.tenant}" +
367 "auth_url={0.auth_url} insecure={0.insecure}").format(creds))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300368
koder aka kdanilovcee43342015-04-14 22:52:53 +0300369 return creds
koder aka kdanilov4e9f3ed2015-04-14 11:26:12 +0300370
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300371
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300372def get_vm_keypair(cfg):
373 res = {}
374 for field, ext in (('keypair_file_private', 'pem'),
375 ('keypair_file_public', 'pub')):
376 fpath = cfg.vm_configs.get(field)
377
378 if fpath is None:
379 fpath = cfg.vm_configs['keypair_name'] + "." + ext
380
381 if os.path.isabs(fpath):
382 res[field] = fpath
383 else:
384 res[field] = os.path.join(cfg.config_folder, fpath)
385 return res
386
387
koder aka kdanilov168f6092015-04-19 02:33:38 +0300388@contextlib.contextmanager
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300389def create_vms_ctx(ctx, cfg, config, already_has_count=0):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300390 if config['count'].startswith('='):
391 count = int(config['count'][1:])
392 if count <= already_has_count:
393 logger.debug("Not need new vms")
394 yield []
395 return
396
397 params = cfg.vm_configs[config['cfg_name']].copy()
koder aka kdanilov168f6092015-04-19 02:33:38 +0300398 os_nodes_ids = []
399
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300400 if not start_vms.is_connected():
401 os_creds = get_OS_credentials(cfg, ctx)
402 else:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300403 os_creds = None
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300404
koder aka kdanilovb7197432015-07-15 00:40:43 +0300405 nova = start_vms.nova_connect(os_creds)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300406
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300407 params.update(config)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300408 params.update(get_vm_keypair(cfg))
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300409
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300410 params['group_name'] = cfg.run_uuid
411 params['keypair_name'] = cfg.vm_configs['keypair_name']
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300412
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300413 if not config.get('skip_preparation', False):
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300414 logger.info("Preparing openstack")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300415 start_vms.prepare_os_subpr(nova, params, os_creds)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300416
417 new_nodes = []
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300418 old_nodes = ctx.nodes[:]
koder aka kdanilov168f6092015-04-19 02:33:38 +0300419 try:
koder aka kdanilov10266f42015-09-10 19:26:08 +0300420 for new_node, node_id in start_vms.launch_vms(nova, params, already_has_count):
koder aka kdanilov168f6092015-04-19 02:33:38 +0300421 new_node.roles.append('testnode')
422 ctx.nodes.append(new_node)
423 os_nodes_ids.append(node_id)
424 new_nodes.append(new_node)
425
426 store_nodes_in_log(cfg, os_nodes_ids)
427 ctx.openstack_nodes_ids = os_nodes_ids
428
429 yield new_nodes
430
431 finally:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300432 if not cfg.keep_vm:
koder aka kdanilov168f6092015-04-19 02:33:38 +0300433 shut_down_vms_stage(cfg, ctx)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300434 ctx.nodes = old_nodes
koder aka kdanilov168f6092015-04-19 02:33:38 +0300435
436
koder aka kdanilovcee43342015-04-14 22:52:53 +0300437def run_tests_stage(cfg, ctx):
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300438 ctx.results = collections.defaultdict(lambda: [])
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300439
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300440 for group in cfg.get('tests', []):
koder aka kdanilovcee43342015-04-14 22:52:53 +0300441
koder aka kdanilov170936a2015-06-27 22:51:17 +0300442 if len(group.items()) != 1:
443 msg = "Items in tests section should have len == 1"
444 logger.error(msg)
445 raise utils.StopTestError(msg)
446
koder aka kdanilovcee43342015-04-14 22:52:53 +0300447 key, config = group.items()[0]
448
449 if 'start_test_nodes' == key:
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300450 if 'openstack' not in config:
451 msg = "No openstack block in config - can't spawn vm's"
452 logger.error(msg)
453 raise utils.StopTestError(msg)
454
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300455 num_test_nodes = 0
456 for node in ctx.nodes:
457 if 'testnode' in node.roles:
458 num_test_nodes += 1
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300459
460 vm_ctx = create_vms_ctx(ctx, cfg, config['openstack'],
461 num_test_nodes)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300462 tests = config.get('tests', [])
463 else:
464 vm_ctx = utils.empty_ctx([])
465 tests = [group]
koder aka kdanilovcee43342015-04-14 22:52:53 +0300466
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300467 if cfg.get('sensors') is None:
468 sensor_ctx = utils.empty_ctx()
469 else:
470 sensor_ctx = with_sensors_util(cfg.get('sensors'), ctx.nodes)
koder aka kdanilovcee43342015-04-14 22:52:53 +0300471
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300472 with vm_ctx as new_nodes:
473 if len(new_nodes) != 0:
474 connect_all(new_nodes, True)
475
476 if not cfg.no_tests:
477 for test_group in tests:
478 with sensor_ctx:
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300479 for tp, res in run_tests(cfg, test_group, ctx.nodes):
480 ctx.results[tp].extend(res)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300481
gstepanov023c1e42015-04-08 15:50:19 +0300482
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300483def shut_down_vms_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300484 vm_ids_fname = cfg.vm_ids_fname
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300485 if ctx.openstack_nodes_ids is None:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300486 nodes_ids = open(vm_ids_fname).read().split()
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300487 else:
488 nodes_ids = ctx.openstack_nodes_ids
489
koder aka kdanilov652cd802015-04-13 12:21:07 +0300490 if len(nodes_ids) != 0:
491 logger.info("Removing nodes")
492 start_vms.clear_nodes(nodes_ids)
493 logger.info("Nodes has been removed")
gstepanov023c1e42015-04-08 15:50:19 +0300494
koder aka kdanilov66839a92015-04-11 13:22:31 +0300495 if os.path.exists(vm_ids_fname):
496 os.remove(vm_ids_fname)
gstepanov023c1e42015-04-08 15:50:19 +0300497
koder aka kdanilov66839a92015-04-11 13:22:31 +0300498
499def store_nodes_in_log(cfg, nodes_ids):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300500 with open(cfg.vm_ids_fname, 'w') as fd:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300501 fd.write("\n".join(nodes_ids))
gstepanov023c1e42015-04-08 15:50:19 +0300502
503
504def clear_enviroment(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300505 if os.path.exists(cfg.vm_ids_fname):
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300506 shut_down_vms_stage(cfg, ctx)
gstepanov023c1e42015-04-08 15:50:19 +0300507
508
koder aka kdanilovda45e882015-04-06 02:24:42 +0300509def disconnect_stage(cfg, ctx):
koder aka kdanilov652cd802015-04-13 12:21:07 +0300510 ssh_utils.close_all_sessions()
511
koder aka kdanilovda45e882015-04-06 02:24:42 +0300512 for node in ctx.nodes:
513 if node.connection is not None:
514 node.connection.close()
515
516
koder aka kdanilov66839a92015-04-11 13:22:31 +0300517def store_raw_results_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300518 if os.path.exists(cfg.raw_results):
519 cont = yaml_load(open(cfg.raw_results).read())
koder aka kdanilov66839a92015-04-11 13:22:31 +0300520 else:
521 cont = []
522
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300523 cont.extend(utils.yamable(ctx.results).items())
koder aka kdanilov66839a92015-04-11 13:22:31 +0300524 raw_data = pretty_yaml.dumps(cont)
525
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300526 with open(cfg.raw_results, "w") as fd:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300527 fd.write(raw_data)
528
529
530def console_report_stage(cfg, ctx):
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300531 first_report = True
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300532 text_rep_fname = cfg.text_report_file
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300533 with open(text_rep_fname, "w") as fd:
534 for tp, data in ctx.results.items():
535 if 'io' == tp and data is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300536 rep_lst = []
537 for result in data:
538 rep_lst.append(
539 IOPerfTest.format_for_console(list(result)))
540 rep = "\n\n".join(rep_lst)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300541 elif tp in ['mysql', 'pgbench'] and data is not None:
542 rep = MysqlTest.format_for_console(data)
543 else:
544 logger.warning("Can't generate text report for " + tp)
545 continue
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300546
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300547 fd.write(rep)
548 fd.write("\n")
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300549
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300550 if first_report:
551 logger.info("Text report were stored in " + text_rep_fname)
552 first_report = False
553
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300554 print("\n" + rep + "\n")
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300555
koder aka kdanilov66839a92015-04-11 13:22:31 +0300556
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300557def test_load_report_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300558 load_rep_fname = cfg.load_report_file
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300559 found = False
560 for idx, (tp, data) in enumerate(ctx.results.items()):
561 if 'io' == tp and data is not None:
562 if found:
563 logger.error("Making reports for more than one " +
564 "io block isn't supported! All " +
565 "report, except first are skipped")
566 continue
567 found = True
568 report.make_load_report(idx, cfg['results'], load_rep_fname)
569
570
koder aka kdanilove87ae652015-04-20 02:14:35 +0300571def html_report_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300572 html_rep_fname = cfg.html_report_file
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300573 found = False
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300574 for tp, data in ctx.results.items():
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300575 if 'io' == tp and data is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300576 if found or len(data) > 1:
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300577 logger.error("Making reports for more than one " +
578 "io block isn't supported! All " +
579 "report, except first are skipped")
580 continue
581 found = True
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300582 report.make_io_report(list(data[0]),
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300583 cfg.get('comment', ''),
584 html_rep_fname,
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300585 lab_info=ctx.hw_info)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300586
koder aka kdanilovda45e882015-04-06 02:24:42 +0300587
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300588def load_data_from_path(test_res_dir):
589 files = get_test_files(test_res_dir)
590 raw_res = yaml_load(open(files['raw_results']).read())
591 res = collections.defaultdict(lambda: [])
koder aka kdanilovda45e882015-04-06 02:24:42 +0300592
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300593 for tp, test_lists in raw_res:
594 for tests in test_lists:
595 for suite_name, suite_data in tests.items():
596 result_folder = suite_data[0]
597 res[tp].append(TOOL_TYPE_MAPPER[tp].load(suite_name, result_folder))
koder aka kdanilovda45e882015-04-06 02:24:42 +0300598
koder aka kdanilov6b872662015-06-23 01:58:36 +0300599 return res
600
601
602def load_data_from_path_stage(var_dir, _, ctx):
603 for tp, vals in load_data_from_path(var_dir).items():
604 ctx.results.setdefault(tp, []).extend(vals)
koder aka kdanilovbc2c8982015-06-13 02:50:43 +0300605
606
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300607def load_data_from(var_dir):
koder aka kdanilov6b872662015-06-23 01:58:36 +0300608 return functools.partial(load_data_from_path_stage, var_dir)