"""
from os import environ, remove
-import socket # For catching socket.timeout.
from tempfile import NamedTemporaryFile
import threading
+import traceback
from robot.api import logger
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=120, include_reason=True
)
logger.console(
f"Extracting tarball to {con.REMOTE_FW_DIR} on {node[u'type']} "
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(
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']}"
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
"""
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(
)
-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(
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"Results: {results}")
+ for log in logs:
+ logger.trace(log)
+
delete_local_tarball(tarball)
if all(results):
logger.console(u"All nodes are ready.")
"""
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)
logger.info(f"Results: {results}")
+ for log in logs:
+ logger.trace(log)
+
if all(results):
logger.console(u"All nodes cleaned up.")
else: