X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FSetupFramework.py;h=26a07c3a3869e5695c034821dbaad3c2afcb846e;hp=7e3b36cc77a8acbe5d136b6e20e14057a935cd05;hb=1e5030b987404fb1cf1dfabe31a150092ff84a3d;hpb=533ce0def99dc776f5a2b9075aaabea000c2dc89 diff --git a/resources/libraries/python/SetupFramework.py b/resources/libraries/python/SetupFramework.py index 7e3b36cc77..26a07c3a38 100644 --- a/resources/libraries/python/SetupFramework.py +++ b/resources/libraries/python/SetupFramework.py @@ -17,9 +17,9 @@ supposed to end up here. """ from os import environ, remove -import socket # For catching socket.timeout. from tempfile import NamedTemporaryFile import threading +import traceback from robot.api import logger @@ -105,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']} " @@ -116,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( @@ -129,7 +133,7 @@ def create_env_directory_at_node(node): f"-p $(which python3) --system-site-packages --never-download env " \ f"&& source env/bin/activate && ANSIBLE_SKIP_CONFLICT_CHECK=1 " \ f"pip3 install -r requirements.txt" - exec_cmd_no_error( + 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']}" @@ -138,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 """ @@ -158,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, socket.timeout) 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( @@ -209,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( @@ -263,10 +279,11 @@ 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) @@ -280,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.") @@ -305,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) @@ -321,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: