X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FSetupFramework.py;h=26a07c3a3869e5695c034821dbaad3c2afcb846e;hp=45447e923b49f41eab22cdd2f9f8ce92e0357078;hb=1e5030b987404fb1cf1dfabe31a150092ff84a3d;hpb=d68951ac245150eeefa6e0f4156e4c1b5c9e9325 diff --git a/resources/libraries/python/SetupFramework.py b/resources/libraries/python/SetupFramework.py index 45447e923b..26a07c3a38 100644 --- a/resources/libraries/python/SetupFramework.py +++ b/resources/libraries/python/SetupFramework.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019 Cisco and/or its affiliates. +# Copyright (c) 2021 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -19,6 +19,7 @@ supposed to end up here. from os import environ, remove from tempfile import NamedTemporaryFile import threading +import traceback from robot.api import logger @@ -104,7 +105,7 @@ def extract_tarball_at_node(tarball, node): node, cmd, message=f"Failed to extract {tarball} at node {node[u'type']} " f"host {node[u'host']}, port {node[u'port']}", - timeout=30, include_reason=True + timeout=90, include_reason=True ) logger.console( f"Extracting tarball to {con.REMOTE_FW_DIR} on {node[u'type']} " @@ -115,9 +116,13 @@ def extract_tarball_at_node(tarball, node): def create_env_directory_at_node(node): """Create fresh virtualenv to a directory, install pip requirements. + Return stdout and stderr of the command, + so we see which installs are behaving weird (e.g. attempting download). + :param node: Node to create virtualenv on. :type node: dict - :returns: nothing + :returns: Stdout and stderr. + :rtype: str, str :raises RuntimeError: When failed to setup virtualenv. """ logger.console( @@ -126,8 +131,9 @@ def create_env_directory_at_node(node): ) cmd = f"cd {con.REMOTE_FW_DIR} && rm -rf env && virtualenv " \ f"-p $(which python3) --system-site-packages --never-download env " \ - f"&& source env/bin/activate && pip3 install -r requirements.txt" - exec_cmd_no_error( + f"&& source env/bin/activate && ANSIBLE_SKIP_CONFLICT_CHECK=1 " \ + f"pip3 install -r requirements.txt" + stdout, stderr = exec_cmd_no_error( node, cmd, timeout=100, include_reason=True, message=f"Failed install at node {node[u'type']} host {node[u'host']}, " f"port {node[u'port']}" @@ -136,19 +142,22 @@ def create_env_directory_at_node(node): f"Virtualenv setup on {node[u'type']} host {node[u'host']}, " f"port {node[u'port']} done." ) + return stdout, stderr -def setup_node(node, tarball, remote_tarball, results=None): +def setup_node(node, tarball, remote_tarball, results=None, logs=None): """Copy a tarball to a node and extract it. :param node: A node where the tarball will be copied and extracted. :param tarball: Local path of tarball to be copied. :param remote_tarball: Remote path of the tarball. :param results: A list where to store the result of node setup, optional. + :param logs: A list where to store anything that should be logged. :type node: dict :type tarball: str :type remote_tarball: str :type results: list + :type logs: list :returns: True - success, False - error :rtype: bool """ @@ -156,12 +165,18 @@ def setup_node(node, tarball, remote_tarball, results=None): copy_tarball_to_node(tarball, node) extract_tarball_at_node(remote_tarball, node) if node[u"type"] == NodeType.TG: - create_env_directory_at_node(node) - except RuntimeError as exc: - logger.console( - f"Node {node[u'type']} host {node[u'host']}, port {node[u'port']} " - f"setup failed, error: {exc!r}" - ) + stdout, stderr = create_env_directory_at_node(node) + if isinstance(logs, list): + logs.append(f"{node[u'host']} Env stdout: {stdout}") + logs.append(f"{node[u'host']} Env stderr: {stderr}") + except Exception: + # any exception must result in result = False + # since this runs in a thread and can't be caught anywhere else + err_msg = f"Node {node[u'type']} host {node[u'host']}, " \ + f"port {node[u'port']} setup failed." + logger.console(err_msg) + if isinstance(logs, list): + logs.append(f"{err_msg} Exception: {traceback.format_exc()}") result = False else: logger.console( @@ -207,23 +222,26 @@ def delete_framework_dir(node): ) -def cleanup_node(node, results=None): +def cleanup_node(node, results=None, logs=None): """Delete a tarball from a node. :param node: A node where the tarball will be delete. :param results: A list where to store the result of node cleanup, optional. + :param logs: A list where to store anything that should be logged. :type node: dict :type results: list + :type logs: list :returns: True - success, False - error :rtype: bool """ try: delete_framework_dir(node) - except RuntimeError: - logger.error( - f"Cleanup of node {node[u'type']} host {node[u'host']}, " - f"port {node[u'port']} failed." - ) + except Exception: + err_msg = f"Cleanup of node {node[u'type']} host {node[u'host']}, " \ + f"port {node[u'port']} failed." + logger.console(err_msg) + if isinstance(logs, list): + logs.append(f"{err_msg} Exception: {traceback.format_exc()}") result = False else: logger.console( @@ -261,16 +279,17 @@ class SetupFramework: remote_tarball = f"{tarball}" results = list() + logs = list() threads = list() for node in nodes.values(): - args = node, tarball, remote_tarball, results + args = node, tarball, remote_tarball, results, logs thread = threading.Thread(target=setup_node, args=args) thread.start() threads.append(thread) logger.info( - f"Executing node setups in parallel, waiting for threads to end" + u"Executing node setups in parallel, waiting for threads to end." ) for thread in threads: @@ -278,6 +297,9 @@ class SetupFramework: logger.info(f"Results: {results}") + for log in logs: + logger.trace(log) + delete_local_tarball(tarball) if all(results): logger.console(u"All nodes are ready.") @@ -303,10 +325,12 @@ class CleanupFramework: """ results = list() + logs = list() threads = list() for node in nodes.values(): - thread = threading.Thread(target=cleanup_node, args=(node, results)) + thread = threading.Thread(target=cleanup_node, + args=(node, results, logs)) thread.start() threads.append(thread) @@ -319,6 +343,9 @@ class CleanupFramework: logger.info(f"Results: {results}") + for log in logs: + logger.trace(log) + if all(results): logger.console(u"All nodes cleaned up.") else: