def test_uid_object(self):
        try:
            uid = Uid()
            key = 'key3'
            relative_path = 'some_relative_path/something3.txt'
            FileRegistry().register_file(key, relative_path)

            with self.subTest('Basic functionality'):
                self.assertEqual(FileRegistry().get_file(key, uid), os.path.join(uid.logs_dir, relative_path))
        finally:
            shutil.rmtree(uid.logs_dir)
    def test_registered_keys(self):
        key = 'key1'
        filename = 'something.txt'
        some_path = '/nobackup/user'
        FileRegistry().register_file(key, filename)

        with self.subTest('Basic functionality'):
            self.assertEqual(FileRegistry().get_file(key, some_path), os.path.join(some_path, filename))

        with self.subTest('Testing duplicate key registrations'):
            with self.assertRaises(KeyAlreadyRegistered):
                FileRegistry().register_file(key, 'something_else')
            self.assertEqual(FileRegistry().get_file(key, some_path), os.path.join(some_path, filename))
Exemple #3
0
    def submit(self, args_from_first_pass: argparse.Namespace, other_args_from_first_pass: list):
        uid = Uid()
        self.uid = uid
        logger.info("FireX ID: %s", uid)
        logger.info('Logs: %s', uid.logs_dir)

        self.install_configs = load_new_install_configs(uid.identifier,
                                                        uid.logs_dir,
                                                        args_from_first_pass.install_configs)
        args, others = self.resolve_install_configs_args(args_from_first_pass, other_args_from_first_pass)

        chain_args = self.process_other_chain_args(args, others)
        chain_args['uid'] = uid

        if args.logs_link:
            self.create_logs_link(args.logs_link)

        if self.install_configs.has_viewer():
            uid.add_viewers(logs_url=self.install_configs.get_logs_root_url())
            logger.info(f'Logs URL: {uid.logs_url}')

        # Create an env file for debugging
        with open(FileRegistry().get_file(ENVIRON_FILE_REGISTRY_KEY, self.uid.logs_dir), 'w') as f:
            json.dump(dict(os.environ), fp=f, skipkeys=True, sort_keys=True, indent=4)

        chain_args = self.convert_chain_args(chain_args)

        chain_args = self.start_engine(args=args, chain_args=chain_args, uid=uid)

        # Execute chain
        try:
            root_task_name = app.conf.get("root_task")
            if root_task_name is None:
                raise NotRegistered("No root task configured")
            root_task = get_app_task(root_task_name)
        except NotRegistered as e:
            logger.error(e)
            self.main_error_exit_handler(reason=str(e))
            sys.exit(-1)
        self.wait_tracking_services_task_ready()

        safe_create_initial_run_json(**chain_args)
        # AsyncResult objects cannot be in memory after the broker (i.e. backend) shutdowns, otherwise errors are
        # produced when they are garbage collected. We therefore monkey patch AsyncResults to track all instances
        # (e.g. from unpickle, instantiated directly, etc) so that disable_all_async_results can disable their
        # references to the backend.
        monkey_patch_async_result_to_track_instances()
        root_task_result_promise = root_task.s(submit_app=self, **chain_args).delay()

        self.copy_submission_log()

        if args.sync:
            logger.info("Waiting for chain to complete...")
            chain_results = self.process_sync(root_task_result_promise, chain_args)
            results_str = self.format_results_str(chain_results)
            self.log_results(results_str)
            self.self_destruct(chain_details=(root_task_result_promise, chain_args),
                               reason="Sync run: completed successfully")
Exemple #4
0
def store_debug_info():
    setup, pydev = get_pydev_debug_setup()
    data = {"pydev": pydev, "setup": setup, "debug_host": gethostname()}

    from firexapp.engine.celery import app
    logs_dir = app.backend.get('logs_dir').decode()
    json_path = FileRegistry().get_file(PYDEV_REGISTRY_KEY, logs_dir)

    print("Storing debugging information", file=sys.stdout)
    with open(json_path, 'w') as outfile:
        json.dump(data, outfile)
    def start(self, args, uid=None, **kwargs)->{}:
        # assemble startup cmd
        if args.recording:
            dest = args.recording
        else:
            dest = FileRegistry().get_file(DEFAULT_RECORDER_DEST_REGISTRY_KEY, uid.logs_dir)
        if not os.path.isdir(os.path.dirname(dest)):
            silent_mkdir(os.path.dirname(dest))

        cmd = "firex_recorder"
        cmd += ' --destination ' + dest
        cmd += ' --broker ' + BrokerFactory.get_broker_url()
        if self.default_timeout:
            cmd += ' --timeout ' + str(self.default_timeout)
        cmd += " &"

        # start the recording service
        logger.debug("Starting Recorder...")
        recorder_stdout = FileRegistry().get_file(RECORDER_LOG_REGISTRY_KEY, uid.logs_dir)
        with open(recorder_stdout, 'wb') as out:
            subprocess.check_call(cmd, shell=True, stdout=out, stderr=subprocess.STDOUT)
Exemple #6
0
    def assert_expected_firex_output(self, cmd_output, cmd_err):
        rec_file = os.path.join(self.results_folder, "recording.rec")
        assert os.path.isfile(rec_file), 'recording file not created'

        logs_dir = get_log_dir_from_output(cmd_output)
        recorder_stdout = FileRegistry().get_file(RECORDER_LOG_REGISTRY_KEY, logs_dir)
        assert os.path.isfile(recorder_stdout), 'recorder output not found'
        with open(recorder_stdout) as f:
            for line in f:
                if line.strip().endswith("Shutting down on broker and root task completion"):
                    break
            else:
                assert False, "Recorder did not log it's own shut down"
Exemple #7
0
 def assert_expected_firex_output(self, cmd_output, cmd_err):
     logs_dir = get_log_dir_from_output(cmd_output)
     recorder_stdout = FileRegistry().get_file(RECORDER_LOG_REGISTRY_KEY, logs_dir)
     assert os.path.isfile(recorder_stdout), 'recorder output not found'
     for _ in range(0, 6):
         # there could be a delay in shutting down. Give it a change to finish
         with open(recorder_stdout) as f:
             for line in f:
                 if line.strip().endswith("Exiting on timeout"):
                     return
             else:
                 import time
                 time.sleep(0.5)
     else:
         assert False, "Recorder did not log it's own shut down"
    def test_dump_and_read_from_file(self):
        FileRegistry().destroy()
        registry = {'key1': 'value1',
                    'key2': 'value2'}
        for k, v in registry.items():
            FileRegistry().register_file(k, v)

        file_registry = tempfile.NamedTemporaryFile().name
        FileRegistry().dump_to_file(file_registry)
        FileRegistry().destroy()
        FileRegistry(from_file=file_registry)
        self.assertDictEqual(FileRegistry().file_registry, registry)
Exemple #9
0
def restart_celery_in_debug():
    from firexapp.engine.celery import app
    firex_logs_dir = app.backend.get('logs_dir').decode()
    json_path = FileRegistry().get_file(PYDEV_REGISTRY_KEY, firex_logs_dir)

    if not os.path.isfile(json_path):
        print("No debugging information found", file=sys.stdout)
        return

    with open(json_path, "r") as infile:
        data = json.load(infile)

    setup = data['setup']
    pydev = data['pydev']
    debug_host = data['debug_host']

    celery_argsv = sys.argv
    debug_celery = get_pydev_command(celery_argsv,
                                     setup=setup,
                                     pydev=pydev,
                                     debug_host=debug_host)
    print("restarting celery in debug mode", file=sys.stdout)
    os.execl(debug_celery[0], *debug_celery)
Exemple #10
0
def get_submission_file(logs_dir: str):
    submission_file = FileRegistry().get_file(SUBMISSION_FILE_REGISTRY_KEY,
                                              logs_dir)
    assert os.path.isfile(submission_file), "submission file missing not there"
    return submission_file
Exemple #11
0
 def copy_submission_log(self):
     if self.submission_tmp_file and os.path.isfile(self.submission_tmp_file) and self.uid:
         copyfile(self.submission_tmp_file, FileRegistry().get_file(SUBMISSION_FILE_REGISTRY_KEY, self.uid.logs_dir))
Exemple #12
0
from firexapp.submit.console import setup_console_logging
from firexapp.application import import_microservices, get_app_tasks, get_app_task
from firexapp.engine.celery import app
from firexapp.broker_manager.broker_factory import BrokerFactory
from firexapp.submit.shutdown import launch_background_shutdown, DEFAULT_CELERY_SHUTDOWN_TIMEOUT
from firexapp.submit.install_configs import load_new_install_configs, FireXInstallConfigs, INSTALL_CONFIGS_ENV_NAME
from firexapp.submit.arguments import whitelist_arguments
from firexapp.common import dict2str, silent_mkdir, create_link
from firexapp.reporters.json_reporter import FireXJsonReportGenerator

add_hostname_to_log_records()
logger = setup_console_logging(__name__)


SUBMISSION_FILE_REGISTRY_KEY = 'firex_submission'
FileRegistry().register_file(SUBMISSION_FILE_REGISTRY_KEY, os.path.join(Uid.debug_dirname, 'submission.txt'))

ENVIRON_FILE_REGISTRY_KEY = 'env'
FileRegistry().register_file(ENVIRON_FILE_REGISTRY_KEY, os.path.join(Uid.debug_dirname, 'environ.json'))


class JsonFileAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):

        if not os.path.isabs(values):
            values = os.path.join(os.getcwd(), values)

        assert not os.path.isdir(values), f'{values} is a directory, you must provide a filename or path'

        if os.path.islink(values) or os.path.isfile(values):
            logger.print(f'--json_file {values} exists; removing it')
Exemple #13
0
import subprocess
from functools import partial

from firexapp.fileregistry import FileRegistry
from firexapp.submit.uid import Uid
from socket import gethostname
from urllib.parse import urlsplit
from logging import ERROR, INFO
from psutil import Process
from pathlib import Path

from firexapp.broker_manager import BrokerManager
from firexapp.common import get_available_port, wait_until, silent_mkdir

REDIS_DIR_REGISTRY_KEY = 'REDIS_DIR_REGISTRY_KEY'
FileRegistry().register_file(REDIS_DIR_REGISTRY_KEY,
                             os.path.join(Uid.debug_dirname, 'redis'))

REDIS_LOG_REGISTRY_KEY = 'REDIS_LOG_REGISTRY_KEY'
FileRegistry().register_file(
    REDIS_LOG_REGISTRY_KEY,
    os.path.join(FileRegistry().get_relative_path(REDIS_DIR_REGISTRY_KEY),
                 'redis.stdout.txt'))

REDIS_PID_REGISTRY_KEY = 'REDIS_PID_REGISTRY_KEY'
FileRegistry().register_file(
    REDIS_PID_REGISTRY_KEY,
    os.path.join(FileRegistry().get_relative_path(REDIS_DIR_REGISTRY_KEY),
                 'redis.pid'))

REDIS_METADATA_REGISTRY_KEY = 'REDIS_METADATA_REGISTRY_KEY'
FileRegistry().register_file(
Exemple #14
0
 def get_worker_logs_dir(logs_dir):
     return FileRegistry().get_file(MICROSERVICE_LOGS_REGISTRY_KEY, logs_dir)
Exemple #15
0
import inspect
import json
import os
import sys
from _socket import gethostname

from firexapp.fileregistry import FileRegistry
from firexapp.submit.uid import Uid

PYDEV_REGISTRY_KEY = 'pydev_debug'
FileRegistry().register_file(
    PYDEV_REGISTRY_KEY, os.path.join(Uid.debug_dirname, 'pydev_debug.json'))


def get_pydev_debug_setup():
    frame = inspect.currentframe()
    all_frames = inspect.getouterframes(frame)
    for i in range(1, len(all_frames)):
        setup_frame = all_frames[-i]
        setup = setup_frame.frame.f_locals.get('setup')
        if setup:
            return setup, setup_frame.filename


def is_debugging():
    frame = inspect.currentframe()
    top_frame = inspect.getouterframes(frame)[-1]
    return "pydevd.py" in top_frame.filename


def is_firex_submit():
Exemple #16
0
import os
import re
import subprocess
import psutil
from firexapp.broker_manager.broker_factory import BrokerFactory
from socket import gethostname
from firexapp.common import poll_until_file_not_empty, poll_until_dir_empty, find_procs
from firexapp.plugins import PLUGGING_ENV_NAME, cdl2list
from firexapp.fileregistry import FileRegistry
from collections.abc import Iterable
from firexapp.common import qualify_firex_bin

logger = setup_console_logging(__name__)

CELERY_LOGS_REGISTRY_KEY = 'celery_logs'
FileRegistry().register_file(CELERY_LOGS_REGISTRY_KEY, os.path.join(Uid.debug_dirname, 'celery'))

CELERY_PIDS_REGISTRY_KEY = 'celery_pids'
FileRegistry().register_file(CELERY_PIDS_REGISTRY_KEY,
                             os.path.join(FileRegistry().get_relative_path(CELERY_LOGS_REGISTRY_KEY), 'pids'))

MICROSERVICE_LOGS_REGISTRY_KEY = 'microservice_logs'
FileRegistry().register_file(MICROSERVICE_LOGS_REGISTRY_KEY, 'microservice_logs')


class CeleryWorkerStartFailed(Exception):
    pass

class CeleryManager(object):
    celery_bin_name = 'celery'
Exemple #17
0
 def get_celery_pids_dir(logs_dir):
     return FileRegistry().get_file(CELERY_PIDS_REGISTRY_KEY, logs_dir)
Exemple #18
0
 def get_pid_file(logs_dir):
     return FileRegistry().get_file(REDIS_PID_REGISTRY_KEY, logs_dir)
Exemple #19
0
 def get_log_file(logs_dir):
     return FileRegistry().get_file(REDIS_LOG_REGISTRY_KEY, logs_dir)
Exemple #20
0
import os
import subprocess

from celery.utils.log import get_task_logger
from firexapp.broker_manager.broker_factory import BrokerFactory
from firexapp.common import silent_mkdir
from firexapp.fileregistry import FileRegistry
from firexapp.submit.uid import Uid
from firexapp.submit.tracking_service import TrackingService


logger = get_task_logger(__name__)


RECORDER_LOG_REGISTRY_KEY = 'RECORDER_OUTPUT_REGISTRY_KEY'
FileRegistry().register_file(RECORDER_LOG_REGISTRY_KEY, os.path.join(Uid.debug_dirname, 'recorder.stdout'))

DEFAULT_RECORDER_DEST_REGISTRY_KEY = 'DEFAULT_RECORDER_DEST_REGISTRY_KEY'
FileRegistry().register_file(DEFAULT_RECORDER_DEST_REGISTRY_KEY, os.path.join(Uid.debug_dirname, 'firex.rec'))


class RecorderLauncher(TrackingService):
    default_timeout = None

    def extra_cli_arguments(self, arg_parser):
        arg_parser.add_argument('--recording', help='A file to record celery events', default=None)

    def start(self, args, uid=None, **kwargs)->{}:
        # assemble startup cmd
        if args.recording:
            dest = args.recording
Exemple #21
0
 def get_metadata_file(logs_dir):
     return FileRegistry().get_file(REDIS_METADATA_REGISTRY_KEY, logs_dir)
 def test_unregistered_key(self):
     some_path = '/nobackup/user'
     with self.assertRaises(KeyNotRegistered):
         FileRegistry().get_file('unregistered_key', some_path)
Exemple #23
0
 def get_password_file(logs_dir):
     return FileRegistry().get_file(REDIS_CREDS_REGISTRY_KEY, logs_dir)
 def tearDown(self):
     FileRegistry().destroy()
     self.assertDictEqual(FileRegistry().file_registry, {})