blob: af317b3d5ee920777aeb29eacaf5a8b25c18117f [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
Yulia Portnovab0c977c2015-12-11 19:23:28 +020029from wally.suits.omgbench import OmgTest
koder aka kdanilovbc2c8982015-06-13 02:50:43 +030030
31
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030032TOOL_TYPE_MAPPER = {
33 "io": IOPerfTest,
34 "pgbench": PgBenchTest,
35 "mysql": MysqlTest,
Yulia Portnovab0c977c2015-12-11 19:23:28 +020036 "omg": OmgTest,
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030037}
koder aka kdanilov63ad2062015-04-27 13:11:40 +030038
koder aka kdanilov57ce4db2015-04-25 21:25:51 +030039
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030040logger = logging.getLogger("wally")
koder aka kdanilovcee43342015-04-14 22:52:53 +030041
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080042
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030043def connect_all(nodes, spawned_node=False):
44 """
45 Connect to all nodes, log errors
46 nodes:[Node] - list of nodes
47 spawned_node:bool - whenever nodes is newly spawned VM
48 """
koder aka kdanilove21d7472015-02-14 19:02:04 -080049
koder aka kdanilov2c473092015-03-29 17:12:13 +030050 logger.info("Connecting to nodes")
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030051
52 conn_timeout = 240 if spawned_node else 30
53
54 def connect_ext(conn_url):
55 try:
56 return ssh_utils.connect(conn_url, conn_timeout=conn_timeout)
57 except Exception as exc:
58 logger.error("During connect to {0}: {1!s}".format(conn_url, exc))
59 return None
60
61 urls = []
62 ssh_pref = "ssh://"
63
64 for node in nodes:
65 if node.conn_url == 'local':
66 urls.append(node.conn_url)
67 elif node.conn_url.startswith(ssh_pref):
68 urls.append(node.conn_url[len(ssh_pref):])
69 else:
70 msg = "Unknown url type {0}".format(node.conn_url)
71 logger.error(msg)
72 raise utils.StopTestError(msg)
73
koder aka kdanilov2c473092015-03-29 17:12:13 +030074 with ThreadPoolExecutor(32) as pool:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030075 for node, conn in zip(nodes, pool.map(connect_ext, urls)):
76 node.connection = conn
77
78 failed_testnodes = []
79 failed_nodes = []
80
81 for node in nodes:
82 if node.connection is None:
83 if 'testnode' in node.roles:
84 failed_testnodes.append(node.get_conn_id())
85 else:
86 failed_nodes.append(node.get_conn_id())
87
88 if failed_nodes != []:
89 msg = "Node(s) {0} would be excluded - can't connect"
90 logger.warning(msg.format(",".join(failed_nodes)))
91
92 if failed_testnodes != []:
93 msg = "Can't connect to testnode(s) " + ",".join(failed_testnodes)
94 logger.error(msg)
95 raise utils.StopTestError(msg)
96
97 if len(failed_nodes) == 0:
98 logger.info("All nodes connected successfully")
koder aka kdanilov2c473092015-03-29 17:12:13 +030099
100
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300101def collect_hw_info_stage(cfg, ctx):
102 if os.path.exists(cfg['hwreport_fname']):
103 msg = "{0} already exists. Skip hw info"
104 logger.info(msg.format(cfg['hwreport_fname']))
105 return
106
107 with ThreadPoolExecutor(32) as pool:
108 connections = (node.connection for node in ctx.nodes)
109 ctx.hw_info.extend(pool.map(get_hw_info, connections))
110
111 with open(cfg['hwreport_fname'], 'w') as hwfd:
112 for node, info in zip(ctx.nodes, ctx.hw_info):
113 hwfd.write("-" * 60 + "\n")
114 hwfd.write("Roles : " + ", ".join(node.roles) + "\n")
115 hwfd.write(str(info) + "\n")
116 hwfd.write("-" * 60 + "\n\n")
117
118 if info.hostname is not None:
119 fname = os.path.join(
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300120 cfg.hwinfo_directory,
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300121 info.hostname + "_lshw.xml")
122
123 with open(fname, "w") as fd:
124 fd.write(info.raw)
125 logger.info("Hardware report stored in " + cfg['hwreport_fname'])
126 logger.debug("Raw hardware info in " + cfg['hwinfo_directory'] + " folder")
127
128
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300129@contextlib.contextmanager
130def suspend_vm_nodes_ctx(unused_nodes):
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300131 pausable_nodes_ids = [node.os_vm_id for node in unused_nodes
132 if node.os_vm_id is not None]
133 non_pausable = len(unused_nodes) - len(pausable_nodes_ids)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300134
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300135 if 0 != non_pausable:
136 logger.warning("Can't pause {0} nodes".format(
137 non_pausable))
138
139 if len(pausable_nodes_ids) != 0:
140 logger.debug("Try to pause {0} unused nodes".format(
141 len(pausable_nodes_ids)))
142 start_vms.pause(pausable_nodes_ids)
143
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300144 try:
145 yield pausable_nodes_ids
146 finally:
147 if len(pausable_nodes_ids) != 0:
148 logger.debug("Unpausing {0} nodes".format(
149 len(pausable_nodes_ids)))
150 start_vms.unpause(pausable_nodes_ids)
151
152
153def generate_result_dir_name(results, name, params):
154 # make a directory for results
155 all_tests_dirs = os.listdir(results)
156
157 if 'name' in params:
158 dir_name = "{0}_{1}".format(name, params['name'])
159 else:
160 for idx in range(len(all_tests_dirs) + 1):
161 dir_name = "{0}_{1}".format(name, idx)
162 if dir_name not in all_tests_dirs:
163 break
164 else:
165 raise utils.StopTestError("Can't select directory for test results")
166
167 return os.path.join(results, dir_name)
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300168
169
170def run_tests(cfg, test_block, nodes):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300171 """
172 Run test from test block
173 """
174 test_nodes = [node for node in nodes if 'testnode' in node.roles]
175 not_test_nodes = [node for node in nodes if 'testnode' not in node.roles]
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300176
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300177 if len(test_nodes) == 0:
178 logger.error("No test nodes found")
179 return
180
koder aka kdanilovcee43342015-04-14 22:52:53 +0300181 for name, params in test_block.items():
koder aka kdanilovcee43342015-04-14 22:52:53 +0300182 results = []
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300183
184 # iterate over all node counts
185 limit = params.get('node_limit', len(test_nodes))
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300186 if isinstance(limit, (int, long)):
187 vm_limits = [limit]
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300188 else:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300189 list_or_tpl = isinstance(limit, (tuple, list))
190 all_ints = list_or_tpl and all(isinstance(climit, (int, long))
191 for climit in limit)
192 if not all_ints:
193 msg = "'node_limit' parameter ion config should" + \
194 "be either int or list if integers, not {0!r}".format(limit)
195 raise ValueError(msg)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300196 vm_limits = limit
koder aka kdanilov652cd802015-04-13 12:21:07 +0300197
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300198 for vm_count in vm_limits:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300199 # select test nodes
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300200 if vm_count == 'all':
201 curr_test_nodes = test_nodes
202 unused_nodes = []
203 else:
204 curr_test_nodes = test_nodes[:vm_count]
205 unused_nodes = test_nodes[vm_count:]
koder aka kdanilove87ae652015-04-20 02:14:35 +0300206
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300207 if 0 == len(curr_test_nodes):
208 continue
koder aka kdanilov652cd802015-04-13 12:21:07 +0300209
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300210 results_path = generate_result_dir_name(cfg.results_storage, name, params)
211 utils.mkdirs_if_unxists(results_path)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300212
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300213 # suspend all unused virtual nodes
214 if cfg.settings.get('suspend_unused_vms', True):
215 suspend_ctx = suspend_vm_nodes_ctx(unused_nodes)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300216 else:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300217 suspend_ctx = utils.empty_ctx()
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300218
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300219 with suspend_ctx:
220 resumable_nodes_ids = [node.os_vm_id for node in curr_test_nodes
221 if node.os_vm_id is not None]
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300222
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300223 if len(resumable_nodes_ids) != 0:
224 logger.debug("Check and unpause {0} nodes".format(
225 len(resumable_nodes_ids)))
226 start_vms.unpause(resumable_nodes_ids)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300227
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300228 sens_nodes = curr_test_nodes + not_test_nodes
229 with sensors_info_util(cfg, sens_nodes) as sensor_data:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300230 test_cls = TOOL_TYPE_MAPPER[name]
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300231
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300232 remote_dir = cfg.default_test_local_folder.format(name=name)
233
234 test_cfg = TestConfig(test_cls.__name__,
235 params=params,
236 test_uuid=cfg.run_uuid,
237 nodes=test_nodes,
238 log_directory=results_path,
239 remote_dir=remote_dir)
240
241 t_start = time.time()
242 res = test_cls(test_cfg).run()
243 t_end = time.time()
244
245 # save sensor data
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300246 if sensor_data is not None:
247 fname = "{0}_{1}.csv".format(int(t_start), int(t_end))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300248 fpath = os.path.join(cfg.sensor_storage, fname)
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300249
250 with open(fpath, "w") as fd:
251 fd.write("\n\n".join(sensor_data))
252
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300253 results.append(res)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300254
255 yield name, results
koder aka kdanilov2c473092015-03-29 17:12:13 +0300256
257
koder aka kdanilovda45e882015-04-06 02:24:42 +0300258def connect_stage(cfg, ctx):
259 ctx.clear_calls_stack.append(disconnect_stage)
260 connect_all(ctx.nodes)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300261 ctx.nodes = [node for node in ctx.nodes if node.connection is not None]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300262
263
koder aka kdanilovda45e882015-04-06 02:24:42 +0300264def discover_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300265 """
266 discover clusters and nodes stage
267 """
koder aka kdanilov652cd802015-04-13 12:21:07 +0300268 if cfg.get('discover') is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300269 discover_objs = [i.strip() for i in cfg.discover.strip().split(",")]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300270
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300271 nodes = discover(ctx,
272 discover_objs,
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300273 cfg.clouds,
274 cfg.results_storage,
275 not cfg.dont_discover_nodes)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300276
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300277 ctx.nodes.extend(nodes)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300278
279 for url, roles in cfg.get('explicit_nodes', {}).items():
280 ctx.nodes.append(Node(url, roles.split(",")))
281
282
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300283def save_nodes_stage(cfg, ctx):
284 cluster = {}
285 for node in ctx.nodes:
286 roles = node.roles[:]
287 if 'testnode' in roles:
288 roles.remove('testnode')
289
290 if len(roles) != 0:
291 cluster[node.conn_url] = roles
292
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300293 with open(cfg.nodes_report_file, "w") as fd:
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300294 fd.write(pretty_yaml.dumps(cluster))
295
296
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300297def reuse_vms_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300298 vms_patterns = cfg.get('clouds', {}).get('openstack', {}).get('vms', [])
299 private_key_path = get_vm_keypair(cfg)['keypair_file_private']
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300300
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300301 for creds in vms_patterns:
302 user_name, vm_name_pattern = creds.split("@", 1)
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300303 msg = "Vm like {0} lookup failed".format(vm_name_pattern)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300304
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300305 with utils.log_error(msg):
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300306 msg = "Looking for vm with name like {0}".format(vm_name_pattern)
307 logger.debug(msg)
308
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300309 if not start_vms.is_connected():
310 os_creds = get_OS_credentials(cfg, ctx)
311 else:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300312 os_creds = None
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300313
koder aka kdanilovb7197432015-07-15 00:40:43 +0300314 conn = start_vms.nova_connect(os_creds)
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300315 for ip, vm_id in start_vms.find_vms(conn, vm_name_pattern):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300316 conn_url = "ssh://{user}@{ip}::{key}".format(user=user_name,
317 ip=ip,
318 key=private_key_path)
319 node = Node(conn_url, ['testnode'])
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300320 node.os_vm_id = vm_id
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300321 ctx.nodes.append(node)
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300322
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300323
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300324def get_OS_credentials(cfg, ctx):
koder aka kdanilovcee43342015-04-14 22:52:53 +0300325 creds = None
koder aka kdanilovb7197432015-07-15 00:40:43 +0300326 os_creds = None
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300327 force_insecure = False
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300328
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300329 if 'openstack' in cfg.clouds:
330 os_cfg = cfg.clouds['openstack']
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300331 if 'OPENRC' in os_cfg:
332 logger.info("Using OS credentials from " + os_cfg['OPENRC'])
koder aka kdanilovb7197432015-07-15 00:40:43 +0300333 creds_tuple = utils.get_creds_openrc(os_cfg['OPENRC'])
334 os_creds = start_vms.OSCreds(*creds_tuple)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300335 elif 'ENV' in os_cfg:
336 logger.info("Using OS credentials from shell environment")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300337 os_creds = start_vms.ostack_get_creds()
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300338 elif 'OS_TENANT_NAME' in os_cfg:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300339 logger.info("Using predefined credentials")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300340 os_creds = start_vms.OSCreds(os_cfg['OS_USERNAME'].strip(),
341 os_cfg['OS_PASSWORD'].strip(),
342 os_cfg['OS_TENANT_NAME'].strip(),
343 os_cfg['OS_AUTH_URL'].strip(),
344 os_cfg.get('OS_INSECURE', False))
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300345
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300346 elif 'OS_INSECURE' in os_cfg:
347 force_insecure = os_cfg.get('OS_INSECURE', False)
348
koder aka kdanilovb7197432015-07-15 00:40:43 +0300349 if os_creds is None and 'fuel' in cfg.clouds and \
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300350 'openstack_env' in cfg.clouds['fuel'] and \
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300351 ctx.fuel_openstack_creds is not None:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300352 logger.info("Using fuel creds")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300353 creds = start_vms.OSCreds(**ctx.fuel_openstack_creds)
354 elif os_creds is None:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300355 logger.error("Can't found OS credentials")
356 raise utils.StopTestError("Can't found OS credentials", None)
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300357
koder aka kdanilovcee43342015-04-14 22:52:53 +0300358 if creds is None:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300359 creds = os_creds
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300360
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300361 if force_insecure and not creds.insecure:
362 creds = start_vms.OSCreds(creds.name,
363 creds.passwd,
364 creds.tenant,
365 creds.auth_url,
366 True)
367
koder aka kdanilovb7197432015-07-15 00:40:43 +0300368 logger.debug(("OS_CREDS: user={0.name} tenant={0.tenant}" +
369 "auth_url={0.auth_url} insecure={0.insecure}").format(creds))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300370
koder aka kdanilovcee43342015-04-14 22:52:53 +0300371 return creds
koder aka kdanilov4e9f3ed2015-04-14 11:26:12 +0300372
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300373
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300374def get_vm_keypair(cfg):
375 res = {}
376 for field, ext in (('keypair_file_private', 'pem'),
377 ('keypair_file_public', 'pub')):
378 fpath = cfg.vm_configs.get(field)
379
380 if fpath is None:
381 fpath = cfg.vm_configs['keypair_name'] + "." + ext
382
383 if os.path.isabs(fpath):
384 res[field] = fpath
385 else:
386 res[field] = os.path.join(cfg.config_folder, fpath)
387 return res
388
389
koder aka kdanilov168f6092015-04-19 02:33:38 +0300390@contextlib.contextmanager
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300391def create_vms_ctx(ctx, cfg, config, already_has_count=0):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300392 if config['count'].startswith('='):
393 count = int(config['count'][1:])
394 if count <= already_has_count:
395 logger.debug("Not need new vms")
396 yield []
397 return
398
399 params = cfg.vm_configs[config['cfg_name']].copy()
koder aka kdanilov168f6092015-04-19 02:33:38 +0300400 os_nodes_ids = []
401
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300402 if not start_vms.is_connected():
403 os_creds = get_OS_credentials(cfg, ctx)
404 else:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300405 os_creds = None
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300406
koder aka kdanilovb7197432015-07-15 00:40:43 +0300407 nova = start_vms.nova_connect(os_creds)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300408
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300409 params.update(config)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300410 params.update(get_vm_keypair(cfg))
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300411
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300412 params['group_name'] = cfg.run_uuid
413 params['keypair_name'] = cfg.vm_configs['keypair_name']
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300414
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300415 if not config.get('skip_preparation', False):
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300416 logger.info("Preparing openstack")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300417 start_vms.prepare_os_subpr(nova, params, os_creds)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300418
419 new_nodes = []
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300420 old_nodes = ctx.nodes[:]
koder aka kdanilov168f6092015-04-19 02:33:38 +0300421 try:
koder aka kdanilov10266f42015-09-10 19:26:08 +0300422 for new_node, node_id in start_vms.launch_vms(nova, params, already_has_count):
koder aka kdanilov168f6092015-04-19 02:33:38 +0300423 new_node.roles.append('testnode')
424 ctx.nodes.append(new_node)
425 os_nodes_ids.append(node_id)
426 new_nodes.append(new_node)
427
428 store_nodes_in_log(cfg, os_nodes_ids)
429 ctx.openstack_nodes_ids = os_nodes_ids
430
431 yield new_nodes
432
433 finally:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300434 if not cfg.keep_vm:
koder aka kdanilov168f6092015-04-19 02:33:38 +0300435 shut_down_vms_stage(cfg, ctx)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300436 ctx.nodes = old_nodes
koder aka kdanilov168f6092015-04-19 02:33:38 +0300437
438
koder aka kdanilovcee43342015-04-14 22:52:53 +0300439def run_tests_stage(cfg, ctx):
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300440 ctx.results = collections.defaultdict(lambda: [])
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300441
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300442 for group in cfg.get('tests', []):
koder aka kdanilovcee43342015-04-14 22:52:53 +0300443
koder aka kdanilov170936a2015-06-27 22:51:17 +0300444 if len(group.items()) != 1:
445 msg = "Items in tests section should have len == 1"
446 logger.error(msg)
447 raise utils.StopTestError(msg)
448
koder aka kdanilovcee43342015-04-14 22:52:53 +0300449 key, config = group.items()[0]
450
451 if 'start_test_nodes' == key:
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300452 if 'openstack' not in config:
453 msg = "No openstack block in config - can't spawn vm's"
454 logger.error(msg)
455 raise utils.StopTestError(msg)
456
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300457 num_test_nodes = 0
458 for node in ctx.nodes:
459 if 'testnode' in node.roles:
460 num_test_nodes += 1
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300461
462 vm_ctx = create_vms_ctx(ctx, cfg, config['openstack'],
463 num_test_nodes)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300464 tests = config.get('tests', [])
465 else:
466 vm_ctx = utils.empty_ctx([])
467 tests = [group]
koder aka kdanilovcee43342015-04-14 22:52:53 +0300468
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300469 if cfg.get('sensors') is None:
470 sensor_ctx = utils.empty_ctx()
471 else:
472 sensor_ctx = with_sensors_util(cfg.get('sensors'), ctx.nodes)
koder aka kdanilovcee43342015-04-14 22:52:53 +0300473
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300474 with vm_ctx as new_nodes:
475 if len(new_nodes) != 0:
476 connect_all(new_nodes, True)
477
478 if not cfg.no_tests:
479 for test_group in tests:
480 with sensor_ctx:
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300481 for tp, res in run_tests(cfg, test_group, ctx.nodes):
482 ctx.results[tp].extend(res)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300483
gstepanov023c1e42015-04-08 15:50:19 +0300484
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300485def shut_down_vms_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300486 vm_ids_fname = cfg.vm_ids_fname
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300487 if ctx.openstack_nodes_ids is None:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300488 nodes_ids = open(vm_ids_fname).read().split()
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300489 else:
490 nodes_ids = ctx.openstack_nodes_ids
491
koder aka kdanilov652cd802015-04-13 12:21:07 +0300492 if len(nodes_ids) != 0:
493 logger.info("Removing nodes")
494 start_vms.clear_nodes(nodes_ids)
495 logger.info("Nodes has been removed")
gstepanov023c1e42015-04-08 15:50:19 +0300496
koder aka kdanilov66839a92015-04-11 13:22:31 +0300497 if os.path.exists(vm_ids_fname):
498 os.remove(vm_ids_fname)
gstepanov023c1e42015-04-08 15:50:19 +0300499
koder aka kdanilov66839a92015-04-11 13:22:31 +0300500
501def store_nodes_in_log(cfg, nodes_ids):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300502 with open(cfg.vm_ids_fname, 'w') as fd:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300503 fd.write("\n".join(nodes_ids))
gstepanov023c1e42015-04-08 15:50:19 +0300504
505
506def clear_enviroment(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300507 if os.path.exists(cfg.vm_ids_fname):
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300508 shut_down_vms_stage(cfg, ctx)
gstepanov023c1e42015-04-08 15:50:19 +0300509
510
koder aka kdanilovda45e882015-04-06 02:24:42 +0300511def disconnect_stage(cfg, ctx):
koder aka kdanilov652cd802015-04-13 12:21:07 +0300512 ssh_utils.close_all_sessions()
513
koder aka kdanilovda45e882015-04-06 02:24:42 +0300514 for node in ctx.nodes:
515 if node.connection is not None:
516 node.connection.close()
517
518
koder aka kdanilov66839a92015-04-11 13:22:31 +0300519def store_raw_results_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300520 if os.path.exists(cfg.raw_results):
521 cont = yaml_load(open(cfg.raw_results).read())
koder aka kdanilov66839a92015-04-11 13:22:31 +0300522 else:
523 cont = []
524
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300525 cont.extend(utils.yamable(ctx.results).items())
koder aka kdanilov66839a92015-04-11 13:22:31 +0300526 raw_data = pretty_yaml.dumps(cont)
527
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300528 with open(cfg.raw_results, "w") as fd:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300529 fd.write(raw_data)
530
531
532def console_report_stage(cfg, ctx):
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300533 first_report = True
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300534 text_rep_fname = cfg.text_report_file
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300535 with open(text_rep_fname, "w") as fd:
536 for tp, data in ctx.results.items():
537 if 'io' == tp and data is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300538 rep_lst = []
539 for result in data:
540 rep_lst.append(
541 IOPerfTest.format_for_console(list(result)))
542 rep = "\n\n".join(rep_lst)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300543 elif tp in ['mysql', 'pgbench'] and data is not None:
544 rep = MysqlTest.format_for_console(data)
Yulia Portnovab0c977c2015-12-11 19:23:28 +0200545 elif tp == 'omg':
546 rep = OmgTest.format_for_console(data)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300547 else:
548 logger.warning("Can't generate text report for " + tp)
549 continue
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300550
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300551 fd.write(rep)
552 fd.write("\n")
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300553
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300554 if first_report:
555 logger.info("Text report were stored in " + text_rep_fname)
556 first_report = False
557
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300558 print("\n" + rep + "\n")
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300559
koder aka kdanilov66839a92015-04-11 13:22:31 +0300560
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300561def test_load_report_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300562 load_rep_fname = cfg.load_report_file
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300563 found = False
564 for idx, (tp, data) in enumerate(ctx.results.items()):
565 if 'io' == tp and data is not None:
566 if found:
567 logger.error("Making reports for more than one " +
568 "io block isn't supported! All " +
569 "report, except first are skipped")
570 continue
571 found = True
572 report.make_load_report(idx, cfg['results'], load_rep_fname)
573
574
koder aka kdanilove87ae652015-04-20 02:14:35 +0300575def html_report_stage(cfg, ctx):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300576 html_rep_fname = cfg.html_report_file
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300577 found = False
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300578 for tp, data in ctx.results.items():
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300579 if 'io' == tp and data is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300580 if found or len(data) > 1:
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300581 logger.error("Making reports for more than one " +
582 "io block isn't supported! All " +
583 "report, except first are skipped")
584 continue
585 found = True
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300586 report.make_io_report(list(data[0]),
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300587 cfg.get('comment', ''),
588 html_rep_fname,
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300589 lab_info=ctx.hw_info)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300590
koder aka kdanilovda45e882015-04-06 02:24:42 +0300591
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300592def load_data_from_path(test_res_dir):
593 files = get_test_files(test_res_dir)
594 raw_res = yaml_load(open(files['raw_results']).read())
595 res = collections.defaultdict(lambda: [])
koder aka kdanilovda45e882015-04-06 02:24:42 +0300596
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300597 for tp, test_lists in raw_res:
598 for tests in test_lists:
599 for suite_name, suite_data in tests.items():
600 result_folder = suite_data[0]
601 res[tp].append(TOOL_TYPE_MAPPER[tp].load(suite_name, result_folder))
koder aka kdanilovda45e882015-04-06 02:24:42 +0300602
koder aka kdanilov6b872662015-06-23 01:58:36 +0300603 return res
604
605
606def load_data_from_path_stage(var_dir, _, ctx):
607 for tp, vals in load_data_from_path(var_dir).items():
608 ctx.results.setdefault(tp, []).extend(vals)
koder aka kdanilovbc2c8982015-06-13 02:50:43 +0300609
610
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300611def load_data_from(var_dir):
koder aka kdanilov6b872662015-06-23 01:58:36 +0300612 return functools.partial(load_data_from_path_stage, var_dir)