blob: 9ae2c9ef46408b724f9b43b638582aef65e7547a [file] [log] [blame]
gstepanov023c1e42015-04-08 15:50:19 +03001import os
koder aka kdanilove21d7472015-02-14 19:02:04 -08002import logging
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +03003import contextlib
koder aka kdanilov73084622016-11-16 21:51:08 +02004from typing import List, Dict, Iterable, Iterator, Tuple, Optional, Union, cast
koder aka kdanilov22d134e2016-11-08 11:33:19 +02005from concurrent.futures import ThreadPoolExecutor, Future
koder aka kdanilov88407ff2015-05-26 15:35:57 +03006
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +02007from .node_interfaces import NodeInfo, IRPCNode
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +03008from .test_run_class import TestRun
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +02009from .discover import discover
koder aka kdanilov22d134e2016-11-08 11:33:19 +020010from . import pretty_yaml, utils, report, ssh_utils, start_vms, hw_info
koder aka kdanilov73084622016-11-16 21:51:08 +020011from .node import setup_rpc, connect
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020012from .config import ConfigBlock, Config
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030013
14from .suits.mysql import MysqlTest
koder aka kdanilov70227062016-11-26 23:23:21 +020015from .suits.itest import TestInputConfig
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030016from .suits.io.fio import IOPerfTest
17from .suits.postgres import PgBenchTest
18from .suits.omgbench import OmgTest
koder aka kdanilovbc2c8982015-06-13 02:50:43 +030019
20
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030021TOOL_TYPE_MAPPER = {
22 "io": IOPerfTest,
23 "pgbench": PgBenchTest,
24 "mysql": MysqlTest,
Yulia Portnovab0c977c2015-12-11 19:23:28 +020025 "omg": OmgTest,
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030026}
koder aka kdanilov63ad2062015-04-27 13:11:40 +030027
koder aka kdanilov57ce4db2015-04-25 21:25:51 +030028
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030029logger = logging.getLogger("wally")
koder aka kdanilovcee43342015-04-14 22:52:53 +030030
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080031
koder aka kdanilov73084622016-11-16 21:51:08 +020032def connect_all(nodes_info: List[NodeInfo], pool: ThreadPoolExecutor, conn_timeout: int = 30) -> List[IRPCNode]:
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020033 """Connect to all nodes, log errors"""
koder aka kdanilove21d7472015-02-14 19:02:04 -080034
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020035 logger.info("Connecting to %s nodes", len(nodes_info))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030036
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020037 def connect_ext(node_info: NodeInfo) -> Tuple[bool, Union[IRPCNode, NodeInfo]]:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030038 try:
koder aka kdanilov73084622016-11-16 21:51:08 +020039 ssh_node = connect(node_info, conn_timeout=conn_timeout)
40 # TODO(koder): need to pass all required rpc bytes to this call
41 return True, setup_rpc(ssh_node, b"")
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030042 except Exception as exc:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030043 logger.error("During connect to {}: {!s}".format(node, exc))
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020044 return False, node_info
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030045
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020046 failed_testnodes = [] # type: List[NodeInfo]
47 failed_nodes = [] # type: List[NodeInfo]
48 ready = [] # type: List[IRPCNode]
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030049
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020050 for ok, node in pool.map(connect_ext, nodes_info):
51 if not ok:
52 node = cast(NodeInfo, node)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030053 if 'testnode' in node.roles:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030054 failed_testnodes.append(node)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030055 else:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030056 failed_nodes.append(node)
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020057 else:
58 ready.append(cast(IRPCNode, node))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030059
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030060 if failed_nodes:
61 msg = "Node(s) {} would be excluded - can't connect"
62 logger.warning(msg.format(",".join(map(str, failed_nodes))))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030063
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030064 if failed_testnodes:
65 msg = "Can't connect to testnode(s) " + \
66 ",".join(map(str, failed_testnodes))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030067 logger.error(msg)
68 raise utils.StopTestError(msg)
69
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030070 if not failed_nodes:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030071 logger.info("All nodes connected successfully")
koder aka kdanilov2c473092015-03-29 17:12:13 +030072
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020073 return ready
koder aka kdanilov2c473092015-03-29 17:12:13 +030074
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020075
koder aka kdanilov73084622016-11-16 21:51:08 +020076def collect_info_stage(ctx: TestRun) -> None:
77 futures = {} # type: Dict[str, Future]
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030078
koder aka kdanilov22d134e2016-11-08 11:33:19 +020079 with ctx.get_pool() as pool:
koder aka kdanilov73084622016-11-16 21:51:08 +020080 for node in ctx.nodes:
81 hw_info_path = "hw_info/{}".format(node.info.node_id())
koder aka kdanilov22d134e2016-11-08 11:33:19 +020082 if hw_info_path not in ctx.storage:
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020083 futures[hw_info_path] = pool.submit(hw_info.get_hw_info, node), node
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030084
koder aka kdanilov73084622016-11-16 21:51:08 +020085 sw_info_path = "sw_info/{}".format(node.info.node_id())
koder aka kdanilov22d134e2016-11-08 11:33:19 +020086 if sw_info_path not in ctx.storage:
87 futures[sw_info_path] = pool.submit(hw_info.get_sw_info, node)
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030088
koder aka kdanilov22d134e2016-11-08 11:33:19 +020089 for path, future in futures.items():
90 ctx.storage[path] = future.result()
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030091
92
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030093@contextlib.contextmanager
koder aka kdanilov73084622016-11-16 21:51:08 +020094def suspend_vm_nodes_ctx(ctx: TestRun, unused_nodes: List[IRPCNode]) -> Iterator[List[int]]:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030095
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020096 pausable_nodes_ids = [cast(int, node.info.os_vm_id)
97 for node in unused_nodes
98 if node.info.os_vm_id is not None]
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030099
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300100 non_pausable = len(unused_nodes) - len(pausable_nodes_ids)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300101
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200102 if non_pausable:
103 logger.warning("Can't pause {} nodes".format(non_pausable))
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300104
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200105 if pausable_nodes_ids:
106 logger.debug("Try to pause {} unused nodes".format(len(pausable_nodes_ids)))
koder aka kdanilov73084622016-11-16 21:51:08 +0200107 with ctx.get_pool() as pool:
108 start_vms.pause(ctx.os_connection, pausable_nodes_ids, pool)
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300109
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300110 try:
111 yield pausable_nodes_ids
112 finally:
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200113 if pausable_nodes_ids:
114 logger.debug("Unpausing {} nodes".format(len(pausable_nodes_ids)))
koder aka kdanilov73084622016-11-16 21:51:08 +0200115 with ctx.get_pool() as pool:
116 start_vms.unpause(ctx.os_connection, pausable_nodes_ids, pool)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300117
118
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200119def run_tests(ctx: TestRun, test_block: ConfigBlock, nodes: List[IRPCNode]) -> None:
koder aka kdanilov22d134e2016-11-08 11:33:19 +0200120 """Run test from test block"""
121
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200122 test_nodes = [node for node in nodes if 'testnode' in node.info.roles]
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300123
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200124 if not test_nodes:
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300125 logger.error("No test nodes found")
126 return
127
koder aka kdanilovcee43342015-04-14 22:52:53 +0300128 for name, params in test_block.items():
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200129 vm_count = params.get('node_limit', None) # type: Optional[int]
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300130
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200131 # select test nodes
132 if vm_count is None:
133 curr_test_nodes = test_nodes
koder aka kdanilov73084622016-11-16 21:51:08 +0200134 unused_nodes = [] # type: List[IRPCNode]
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300135 else:
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200136 curr_test_nodes = test_nodes[:vm_count]
137 unused_nodes = test_nodes[vm_count:]
koder aka kdanilov652cd802015-04-13 12:21:07 +0300138
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200139 if not curr_test_nodes:
140 logger.error("No nodes found for test, skipping it.")
141 continue
koder aka kdanilove87ae652015-04-20 02:14:35 +0300142
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200143 # results_path = generate_result_dir_name(cfg.results_storage, name, params)
144 # utils.mkdirs_if_unxists(results_path)
koder aka kdanilov652cd802015-04-13 12:21:07 +0300145
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200146 # suspend all unused virtual nodes
147 if ctx.config.get('suspend_unused_vms', True):
koder aka kdanilov73084622016-11-16 21:51:08 +0200148 suspend_ctx = suspend_vm_nodes_ctx(ctx, unused_nodes)
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200149 else:
150 suspend_ctx = utils.empty_ctx()
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300151
koder aka kdanilov73084622016-11-16 21:51:08 +0200152 resumable_nodes_ids = [cast(int, node.info.os_vm_id)
153 for node in curr_test_nodes
154 if node.info.os_vm_id is not None]
155
156 if resumable_nodes_ids:
157 logger.debug("Check and unpause {} nodes".format(len(resumable_nodes_ids)))
158
159 with ctx.get_pool() as pool:
160 start_vms.unpause(ctx.os_connection, resumable_nodes_ids, pool)
161
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200162 with suspend_ctx:
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200163 test_cls = TOOL_TYPE_MAPPER[name]
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200164 remote_dir = ctx.config.default_test_local_folder.format(name=name, uuid=ctx.config.run_uuid)
koder aka kdanilov70227062016-11-26 23:23:21 +0200165 test_cfg = TestInputConfig(test_cls.__name__,
166 params=params,
167 run_uuid=ctx.config.run_uuid,
168 nodes=test_nodes,
169 storage=ctx.storage,
170 remote_dir=remote_dir)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300171
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200172 test_cls(test_cfg).run()
koder aka kdanilov2c473092015-03-29 17:12:13 +0300173
174
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200175def connect_stage(ctx: TestRun) -> None:
koder aka kdanilovda45e882015-04-06 02:24:42 +0300176 ctx.clear_calls_stack.append(disconnect_stage)
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200177
178 with ctx.get_pool() as pool:
koder aka kdanilov73084622016-11-16 21:51:08 +0200179 ctx.nodes = connect_all(ctx.nodes_info, pool)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300180
181
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200182def discover_stage(ctx: TestRun) -> None:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300183 """discover clusters and nodes stage"""
184
koder aka kdanilov73084622016-11-16 21:51:08 +0200185 # TODO(koder): Properly store discovery info and check if it available to skip phase
186
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200187 discover_info = ctx.config.get('discover')
188 if discover_info:
koder aka kdanilov73084622016-11-16 21:51:08 +0200189 if "discovered_nodes" in ctx.storage:
190 nodes = ctx.storage.load_list("discovered_nodes", NodeInfo)
191 ctx.fuel_openstack_creds = ctx.storage.load("fuel_openstack_creds", start_vms.OSCreds)
192 else:
193 discover_objs = [i.strip() for i in discover_info.strip().split(",")]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300194
koder aka kdanilov70227062016-11-26 23:23:21 +0200195 ctx.fuel_openstack_creds, nodes = discover.discover(ctx,
196 discover_objs,
koder aka kdanilov73084622016-11-16 21:51:08 +0200197 ctx.config.clouds,
198 not ctx.config.dont_discover_nodes)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300199
koder aka kdanilov73084622016-11-16 21:51:08 +0200200 ctx.storage["fuel_openstack_creds"] = ctx.fuel_openstack_creds # type: ignore
201 ctx.storage["discovered_nodes"] = nodes # type: ignore
202 ctx.nodes_info.extend(nodes)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300203
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200204 for url, roles in ctx.config.get('explicit_nodes', {}).items():
koder aka kdanilov73084622016-11-16 21:51:08 +0200205 creds = ssh_utils.parse_ssh_uri(url)
206 roles = set(roles.split(","))
207 ctx.nodes_info.append(NodeInfo(creds, roles))
koder aka kdanilovda45e882015-04-06 02:24:42 +0300208
209
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200210def save_nodes_stage(ctx: TestRun) -> None:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300211 """Save nodes list to file"""
koder aka kdanilov73084622016-11-16 21:51:08 +0200212 ctx.storage['nodes'] = ctx.nodes_info # type: ignore
213
214
215def ensure_connected_to_openstack(ctx: TestRun) -> None:
216 if not ctx.os_connection is None:
217 if ctx.os_creds is None:
218 ctx.os_creds = get_OS_credentials(ctx)
219 ctx.os_connection = start_vms.os_connect(ctx.os_creds)
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300220
221
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200222def reuse_vms_stage(ctx: TestRun) -> None:
koder aka kdanilov73084622016-11-16 21:51:08 +0200223 if "reused_nodes" in ctx.storage:
224 ctx.nodes_info.extend(ctx.storage.load_list("reused_nodes", NodeInfo))
225 else:
226 reused_nodes = []
227 vms_patterns = ctx.config.get('clouds/openstack/vms', [])
228 private_key_path = get_vm_keypair_path(ctx.config)[0]
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300229
koder aka kdanilov73084622016-11-16 21:51:08 +0200230 for creds in vms_patterns:
231 user_name, vm_name_pattern = creds.split("@", 1)
232 msg = "Vm like {} lookup failed".format(vm_name_pattern)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300233
koder aka kdanilov73084622016-11-16 21:51:08 +0200234 with utils.LogError(msg):
235 msg = "Looking for vm with name like {0}".format(vm_name_pattern)
236 logger.debug(msg)
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300237
koder aka kdanilov73084622016-11-16 21:51:08 +0200238 ensure_connected_to_openstack(ctx)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300239
koder aka kdanilov73084622016-11-16 21:51:08 +0200240 for ip, vm_id in start_vms.find_vms(ctx.os_connection, vm_name_pattern):
241 creds = ssh_utils.ConnCreds(host=ip, user=user_name, key_file=private_key_path)
242 node_info = NodeInfo(creds, {'testnode'})
243 node_info.os_vm_id = vm_id
244 reused_nodes.append(node_info)
245 ctx.nodes_info.append(node_info)
246
247 ctx.storage["reused_nodes"] = reused_nodes # type: ignore
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300248
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300249
koder aka kdanilov73084622016-11-16 21:51:08 +0200250def get_OS_credentials(ctx: TestRun) -> start_vms.OSCreds:
251
252 if "openstack_openrc" in ctx.storage:
253 return ctx.storage.load("openstack_openrc", start_vms.OSCreds)
254
koder aka kdanilovcee43342015-04-14 22:52:53 +0300255 creds = None
koder aka kdanilovb7197432015-07-15 00:40:43 +0300256 os_creds = None
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300257 force_insecure = False
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200258 cfg = ctx.config
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300259
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300260 if 'openstack' in cfg.clouds:
261 os_cfg = cfg.clouds['openstack']
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300262 if 'OPENRC' in os_cfg:
263 logger.info("Using OS credentials from " + os_cfg['OPENRC'])
koder aka kdanilovb7197432015-07-15 00:40:43 +0300264 creds_tuple = utils.get_creds_openrc(os_cfg['OPENRC'])
265 os_creds = start_vms.OSCreds(*creds_tuple)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300266 elif 'ENV' in os_cfg:
267 logger.info("Using OS credentials from shell environment")
koder aka kdanilov73084622016-11-16 21:51:08 +0200268 os_creds = start_vms.get_openstack_credentials()
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300269 elif 'OS_TENANT_NAME' in os_cfg:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300270 logger.info("Using predefined credentials")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300271 os_creds = start_vms.OSCreds(os_cfg['OS_USERNAME'].strip(),
272 os_cfg['OS_PASSWORD'].strip(),
273 os_cfg['OS_TENANT_NAME'].strip(),
274 os_cfg['OS_AUTH_URL'].strip(),
275 os_cfg.get('OS_INSECURE', False))
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300276
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300277 elif 'OS_INSECURE' in os_cfg:
278 force_insecure = os_cfg.get('OS_INSECURE', False)
279
koder aka kdanilov73084622016-11-16 21:51:08 +0200280 if os_creds is None and 'fuel' in cfg.clouds and 'openstack_env' in cfg.clouds['fuel'] and \
281 ctx.fuel_openstack_creds is not None:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300282 logger.info("Using fuel creds")
koder aka kdanilov73084622016-11-16 21:51:08 +0200283 creds = ctx.fuel_openstack_creds
koder aka kdanilovb7197432015-07-15 00:40:43 +0300284 elif os_creds is None:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300285 logger.error("Can't found OS credentials")
286 raise utils.StopTestError("Can't found OS credentials", None)
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300287
koder aka kdanilovcee43342015-04-14 22:52:53 +0300288 if creds is None:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300289 creds = os_creds
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300290
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300291 if force_insecure and not creds.insecure:
292 creds = start_vms.OSCreds(creds.name,
293 creds.passwd,
294 creds.tenant,
295 creds.auth_url,
296 True)
297
koder aka kdanilov05e15b92016-02-07 19:32:46 +0200298 logger.debug(("OS_CREDS: user={0.name} tenant={0.tenant} " +
koder aka kdanilovb7197432015-07-15 00:40:43 +0300299 "auth_url={0.auth_url} insecure={0.insecure}").format(creds))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300300
koder aka kdanilov73084622016-11-16 21:51:08 +0200301 ctx.storage["openstack_openrc"] = creds # type: ignore
koder aka kdanilovcee43342015-04-14 22:52:53 +0300302 return creds
koder aka kdanilov4e9f3ed2015-04-14 11:26:12 +0300303
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300304
koder aka kdanilov73084622016-11-16 21:51:08 +0200305def get_vm_keypair_path(cfg: Config) -> Tuple[str, str]:
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200306 key_name = cfg.vm_configs['keypair_name']
307 private_path = os.path.join(cfg.settings_dir, key_name + "_private.pem")
308 public_path = os.path.join(cfg.settings_dir, key_name + "_public.pub")
309 return (private_path, public_path)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300310
311
koder aka kdanilov168f6092015-04-19 02:33:38 +0300312@contextlib.contextmanager
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200313def create_vms_ctx(ctx: TestRun, vm_config: ConfigBlock, already_has_count: int = 0) -> Iterator[List[NodeInfo]]:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300314
koder aka kdanilov73084622016-11-16 21:51:08 +0200315 if 'spawned_vm_ids' in ctx.storage:
316 os_nodes_ids = ctx.storage.get('spawned_vm_ids', []) # type: List[int]
317 new_nodes = [] # type: List[NodeInfo]
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300318
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200319 # TODO(koder): reconnect to old VM's
320 raise NotImplementedError("Reconnect to old vms is not implemented")
koder aka kdanilov73084622016-11-16 21:51:08 +0200321 else:
322 os_nodes_ids = []
323 new_nodes = []
324 no_spawn = False
325 if vm_config['count'].startswith('='):
326 count = int(vm_config['count'][1:])
327 if count <= already_has_count:
328 logger.debug("Not need new vms")
329 no_spawn = True
koder aka kdanilov168f6092015-04-19 02:33:38 +0300330
koder aka kdanilov73084622016-11-16 21:51:08 +0200331 if not no_spawn:
332 ensure_connected_to_openstack(ctx)
333 params = ctx.config.vm_configs[vm_config['cfg_name']].copy()
334 params.update(vm_config)
335 params.update(get_vm_keypair_path(ctx.config))
336 params['group_name'] = ctx.config.run_uuid
337 params['keypair_name'] = ctx.config.vm_configs['keypair_name']
koder aka kdanilov168f6092015-04-19 02:33:38 +0300338
koder aka kdanilov73084622016-11-16 21:51:08 +0200339 if not vm_config.get('skip_preparation', False):
340 logger.info("Preparing openstack")
341 start_vms.prepare_os(ctx.os_connection, params)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300342
koder aka kdanilov73084622016-11-16 21:51:08 +0200343 with ctx.get_pool() as pool:
344 for node_info in start_vms.launch_vms(ctx.os_connection, params, pool, already_has_count):
345 node_info.roles.add('testnode')
346 os_nodes_ids.append(node_info.os_vm_id)
347 new_nodes.append(node_info)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300348
koder aka kdanilov73084622016-11-16 21:51:08 +0200349 ctx.storage['spawned_vm_ids'] = os_nodes_ids # type: ignore
350 yield new_nodes
351
352 # keep nodes in case of error for future test restart
353 if not ctx.config.keep_vm:
354 shut_down_vms_stage(ctx, os_nodes_ids)
355
356 del ctx.storage['spawned_vm_ids']
357
358
359@contextlib.contextmanager
360def sensor_monitoring(ctx: TestRun, cfg: ConfigBlock, nodes: List[IRPCNode]) -> Iterator[None]:
361 yield
koder aka kdanilov168f6092015-04-19 02:33:38 +0300362
363
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200364def run_tests_stage(ctx: TestRun) -> None:
365 for group in ctx.config.get('tests', []):
koder aka kdanilov22d134e2016-11-08 11:33:19 +0200366 gitems = list(group.items())
367 if len(gitems) != 1:
koder aka kdanilov170936a2015-06-27 22:51:17 +0300368 msg = "Items in tests section should have len == 1"
369 logger.error(msg)
370 raise utils.StopTestError(msg)
371
koder aka kdanilov22d134e2016-11-08 11:33:19 +0200372 key, config = gitems[0]
koder aka kdanilovcee43342015-04-14 22:52:53 +0300373
374 if 'start_test_nodes' == key:
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300375 if 'openstack' not in config:
376 msg = "No openstack block in config - can't spawn vm's"
377 logger.error(msg)
378 raise utils.StopTestError(msg)
379
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200380 num_test_nodes = len([node for node in ctx.nodes if 'testnode' in node.info.roles])
381 vm_ctx = create_vms_ctx(ctx, config['openstack'], num_test_nodes)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300382 tests = config.get('tests', [])
383 else:
384 vm_ctx = utils.empty_ctx([])
385 tests = [group]
koder aka kdanilovcee43342015-04-14 22:52:53 +0300386
koder aka kdanilov73084622016-11-16 21:51:08 +0200387 # make mypy happy
388 new_nodes = [] # type: List[NodeInfo]
389
390 with vm_ctx as new_nodes:
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200391 if new_nodes:
392 with ctx.get_pool() as pool:
koder aka kdanilov73084622016-11-16 21:51:08 +0200393 new_rpc_nodes = connect_all(new_nodes, pool)
koder aka kdanilovcee43342015-04-14 22:52:53 +0300394
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200395 test_nodes = ctx.nodes + new_rpc_nodes
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300396
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200397 if ctx.config.get('sensors'):
koder aka kdanilov73084622016-11-16 21:51:08 +0200398 sensor_ctx = sensor_monitoring(ctx, ctx.config.get('sensors'), test_nodes)
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200399 else:
400 sensor_ctx = utils.empty_ctx([])
401
402 if not ctx.config.no_tests:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300403 for test_group in tests:
404 with sensor_ctx:
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200405 run_tests(ctx, test_group, test_nodes)
406
407 for node in new_rpc_nodes:
408 node.disconnect()
koder aka kdanilovda45e882015-04-06 02:24:42 +0300409
gstepanov023c1e42015-04-08 15:50:19 +0300410
koder aka kdanilov70227062016-11-26 23:23:21 +0200411def clouds_connect_stage(ctx: TestRun) -> None:
412 # TODO(koder): need to use this to connect to openstack in upper code
413 # conn = ctx.config['clouds/openstack']
414 # user, passwd, tenant = parse_creds(conn['creds'])
415 # auth_data = dict(auth_url=conn['auth_url'],
416 # username=user,
417 # api_key=passwd,
418 # project_id=tenant) # type: Dict[str, str]
419 # logger.debug("Discovering openstack nodes with connection details: %r", conn)
420 # connect to openstack, fuel
421
422 # # parse FUEL REST credentials
423 # username, tenant_name, password = parse_creds(fuel_data['creds'])
424 # creds = {"username": username,
425 # "tenant_name": tenant_name,
426 # "password": password}
427 #
428 # # connect to FUEL
429 # conn = fuel_rest_api.KeystoneAuth(fuel_data['url'], creds, headers=None)
430 pass
431
432
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200433def shut_down_vms_stage(ctx: TestRun, nodes_ids: List[int]) -> None:
434 if nodes_ids:
koder aka kdanilov652cd802015-04-13 12:21:07 +0300435 logger.info("Removing nodes")
koder aka kdanilov73084622016-11-16 21:51:08 +0200436 start_vms.clear_nodes(ctx.os_connection, nodes_ids)
koder aka kdanilov652cd802015-04-13 12:21:07 +0300437 logger.info("Nodes has been removed")
gstepanov023c1e42015-04-08 15:50:19 +0300438
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200439
440def clear_enviroment(ctx: TestRun) -> None:
441 shut_down_vms_stage(ctx, ctx.storage.get('spawned_vm_ids', []))
koder aka kdanilov73084622016-11-16 21:51:08 +0200442 ctx.storage['spawned_vm_ids'] = [] # type: ignore
gstepanov023c1e42015-04-08 15:50:19 +0300443
koder aka kdanilov66839a92015-04-11 13:22:31 +0300444
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200445def disconnect_stage(ctx: TestRun) -> None:
446 # TODO(koder): what next line was for?
447 # ssh_utils.close_all_sessions()
koder aka kdanilov652cd802015-04-13 12:21:07 +0300448
koder aka kdanilovda45e882015-04-06 02:24:42 +0300449 for node in ctx.nodes:
koder aka kdanilov22d134e2016-11-08 11:33:19 +0200450 node.disconnect()
koder aka kdanilovda45e882015-04-06 02:24:42 +0300451
452
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200453def console_report_stage(ctx: TestRun) -> None:
454 # TODO(koder): load data from storage
455 raise NotImplementedError("...")
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300456
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +0200457def html_report_stage(ctx: TestRun) -> None:
458 # TODO(koder): load data from storage
459 raise NotImplementedError("...")