Пример #1
0
def start_daemon():
    """Start a daemon runner for the currently configured profile."""
    daemon_client = get_daemon_client()
    configure_logging(daemon=True,
                      daemon_log_file=daemon_client.daemon_log_file)

    try:
        manager = get_manager()
        runner = manager.create_daemon_runner()
        manager.set_runner(runner)
    except Exception as exception:
        LOGGER.exception('daemon runner failed to start')
        raise

    def shutdown_daemon(_num, _frame):
        LOGGER.info('Received signal to shut down the daemon runner')
        runner.close()

    signal.signal(signal.SIGINT, shutdown_daemon)
    signal.signal(signal.SIGTERM, shutdown_daemon)

    LOGGER.info('Starting a daemon runner')

    try:
        runner.start()
    except SystemError as exception:
        LOGGER.info('Received a SystemError: %s', exception)
        runner.close()

    LOGGER.info('Daemon runner stopped')
Пример #2
0
def retriever():
    configure_logging(daemon=True, daemon_log_file=DAEMON_LOG_FILE)
    from aiida.daemon.execmanager import retrieve_jobs
    LOGGER.info('Checking for calculations to retrieve')
    set_daemon_timestamp(task_name='retriever', when='start')
    retrieve_jobs()
    set_daemon_timestamp(task_name='retriever', when='stop')
Пример #3
0
def start_daemon() -> None:
    """Start a daemon runner for the currently configured profile."""
    daemon_client = get_daemon_client()
    configure_logging(daemon=True, daemon_log_file=daemon_client.daemon_log_file)

    try:
        manager = get_manager()
        runner = manager.create_daemon_runner()
        manager.set_runner(runner)
    except Exception:
        LOGGER.exception('daemon runner failed to start')
        raise

    signals = (signal.SIGTERM, signal.SIGINT)
    for s in signals:  # pylint: disable=invalid-name
        runner.loop.add_signal_handler(s, lambda s=s: asyncio.create_task(shutdown_runner(runner)))

    try:
        LOGGER.info('Starting a daemon runner')
        runner.start()
    except SystemError as exception:
        LOGGER.info('Received a SystemError: %s', exception)
        runner.close()

    LOGGER.info('Daemon runner started')
Пример #4
0
def start_daemon():
    """
    Start a daemon runner for the currently configured profile
    """
    daemon_client = DaemonClient()
    configure_logging(daemon=True,
                      daemon_log_file=daemon_client.daemon_log_file)

    runner = DaemonRunner(rmq_config=get_rmq_config(), rmq_submit=False)

    def shutdown_daemon(num, frame):
        logger.info('Received signal to shut down the daemon runner')
        runner.close()

    signal.signal(signal.SIGINT, shutdown_daemon)
    signal.signal(signal.SIGTERM, shutdown_daemon)

    logger.info('Starting a daemon runner')

    set_runner(runner)
    tick_legacy_workflows(runner)

    try:
        runner.start()
    except SystemError as exception:
        logger.info('Received a SystemError: {}'.format(exception))
        runner.close()

    logger.info('Daemon runner stopped')
Пример #5
0
    def _load_backend(self, schema_check=True):
        """Load the backend for the currently configured profile and return it.

        .. note:: this will reconstruct the `Backend` instance in `self._backend` so the preferred method to load the
            backend is to call `get_backend` which will create it only when not yet instantiated.

        :param schema_check: force a database schema check if the database environment has not yet been loaded
        :return: the database backend
        :rtype: :class:`aiida.orm.implementation.Backend`
        """
        from aiida.backends import BACKEND_DJANGO, BACKEND_SQLA
        from aiida.common import ConfigurationError, InvalidOperation
        from aiida.common.log import configure_logging
        from aiida.manage import configuration

        profile = self.get_profile()

        if profile is None:
            raise ConfigurationError(
                'Could not determine the current profile. Consider loading a profile using `aiida.load_profile()`.'
            )

        if configuration.BACKEND_UUID is not None and configuration.BACKEND_UUID != profile.uuid:
            raise InvalidOperation(
                'cannot load backend because backend of another profile is already loaded'
            )

        backend_type = profile.database_backend

        if backend_type == BACKEND_DJANGO:
            from aiida.backends.djsite.utils import load_dbenv, _load_dbenv_noschemacheck
            load_backend = load_dbenv if schema_check else _load_dbenv_noschemacheck
        elif backend_type == BACKEND_SQLA:
            from aiida.backends.sqlalchemy.utils import load_dbenv, _load_dbenv_noschemacheck
            load_backend = load_dbenv if schema_check else _load_dbenv_noschemacheck
        else:
            raise ConfigurationError(
                'Invalid backend type {} in profile: {}'.format(
                    backend_type, profile.name))

        # Do NOT reload the backend environment if already loaded, simply reload the backend instance after
        if configuration.BACKEND_UUID is None:
            load_backend(profile)
            configuration.BACKEND_UUID = profile.uuid

        # Can only import the backend classes after the backend has been loaded
        if backend_type == BACKEND_DJANGO:
            from aiida.orm.implementation.django.backend import DjangoBackend
            self._backend = DjangoBackend()
        elif backend_type == BACKEND_SQLA:
            from aiida.orm.implementation.sqlalchemy.backend import SqlaBackend
            self._backend = SqlaBackend()

        # Reconfigure the logging with `with_orm=True` to make sure that profile specific logging configuration options
        # are taken into account and the `DbLogHandler` is configured.
        configure_logging(with_orm=True)

        return self._backend
Пример #6
0
def reset_log_level():
    """Reset the `aiida.common.log.CLI_LOG_LEVEL` global and reconfigure the logging.

    This fixture should be used by tests that will change the ``CLI_LOG_LEVEL`` global, for example, through the
    :class:`~aiida.cmdline.params.options.main.VERBOSITY` option in a CLI command invocation.
    """
    from aiida.common import log

    try:
        yield
    finally:
        log.CLI_LOG_LEVEL = None
        log.configure_logging()
Пример #7
0
def override_logging():
    """Return a `SandboxFolder`."""
    from aiida.common.log import configure_logging

    config = get_config()

    try:
        config.set_option('logging.aiida_loglevel', 'DEBUG')
        config.set_option('logging.db_loglevel', 'DEBUG')
        configure_logging(with_orm=True)
        yield
    finally:
        config.unset_option('logging.aiida_loglevel')
        config.unset_option('logging.db_loglevel')
        configure_logging(with_orm=True)
Пример #8
0
def load_profile(profile=None):
    """Load a profile.

    .. note:: if a profile is already loaded and no explicit profile is specified, nothing will be done

    :param profile: the name of the profile to load, by default will use the one marked as default in the config
    :type profile: str

    :return: the loaded `Profile` instance
    :rtype: :class:`~aiida.manage.configuration.Profile`
    :raises `aiida.common.exceptions.InvalidOperation`: if the backend of another profile has already been loaded
    """
    from aiida.common import InvalidOperation
    from aiida.common.log import configure_logging

    global PROFILE
    global BACKEND_UUID

    # If a profile is loaded and the specified profile name is None or that of the currently loaded, do nothing
    if PROFILE and (profile is None or PROFILE.name is profile):
        return PROFILE

    profile = get_config().get_profile(profile)

    if BACKEND_UUID is not None and BACKEND_UUID != profile.uuid:
        # Once the switching of profiles with different backends becomes possible, the backend has to be reset properly
        raise InvalidOperation(
            'cannot switch profile because backend of another profile is already loaded'
        )

    # Set the global variable and make sure the repository is configured
    PROFILE = profile
    PROFILE.configure_repository()

    # Reconfigure the logging to make sure that profile specific logging configuration options are taken into account.
    # Note that we do not configure with `with_orm=True` because that will force the backend to be loaded. This should
    # instead be done lazily in `Manager._load_backend`.
    configure_logging()

    return PROFILE
Пример #9
0
def test_manager(backend=BACKEND_DJANGO, profile_name=None, pgtest=None):
    """ Context manager for TestManager objects.

    Sets up temporary AiiDA environment for testing or reuses existing environment,
    if `AIIDA_TEST_PROFILE` environment variable is set.

    Example pytest fixture::

        def aiida_profile():
            with test_manager(backend) as test_mgr:
                yield fixture_mgr

    Example unittest test runner::

        with test_manager(backend) as test_mgr:
            # ready for tests
        # everything cleaned up


    :param backend: database backend, either BACKEND_SQLA or BACKEND_DJANGO
    :param profile_name: name of test profile to be used or None (to use temporary profile)
    :param pgtest: a dictionary of arguments to be passed to PGTest() for starting the postgresql cluster,
       e.g. {'pg_ctl': '/somepath/pg_ctl'}. Should usually not be necessary.
    """
    from aiida.common.utils import Capturing
    from aiida.common.log import configure_logging

    try:
        if not _GLOBAL_TEST_MANAGER.has_profile_open():
            if profile_name:
                _GLOBAL_TEST_MANAGER.use_profile(profile_name=profile_name)
            else:
                with Capturing():  # capture output of AiiDA DB setup
                    _GLOBAL_TEST_MANAGER.use_temporary_profile(backend=backend,
                                                               pgtest=pgtest)
        configure_logging(with_orm=True)
        yield _GLOBAL_TEST_MANAGER
    finally:
        _GLOBAL_TEST_MANAGER.destroy_all()
Пример #10
0
def workflow_stepper():  # daemon for legacy workflow
    configure_logging(daemon=True, daemon_log_file=DAEMON_LOG_FILE)
    from aiida.daemon.workflowmanager import execute_steps
    LOGGER.info('Checking for workflows to manage')
    # RUDIMENTARY way to check if this task is already running (to avoid acting
    # again and again on the same workflow steps)
    try:
        stepper_is_running = (get_last_daemon_timestamp(
            'workflow', when='stop') - get_last_daemon_timestamp(
                'workflow', when='start')) <= timedelta(0)
    except TypeError:
        # when some timestamps are None (undefined)
        stepper_is_running = (
            get_last_daemon_timestamp('workflow', when='stop') is None and
            get_last_daemon_timestamp('workflow', when='start') is not None)

    if not stepper_is_running:
        set_daemon_timestamp(task_name='workflow', when='start')
        # the previous wf manager stopped already -> we can run a new one
        LOGGER.info('running execute_steps')
        execute_steps()
        set_daemon_timestamp(task_name='workflow', when='stop')
    else:
        LOGGER.info('execute_steps already running')
Пример #11
0
__copyright__ = (
    u'Copyright (c), This file is part of the AiiDA platform. '
    u'For further information please visit http://www.aiida.net/. All rights reserved.'
)
__license__ = 'MIT license, see LICENSE.txt file.'
__version__ = '1.0.1'
__authors__ = 'The AiiDA team.'
__paper__ = (
    u'G. Pizzi, A. Cepellotti, R. Sabatini, N. Marzari, and B. Kozinsky,'
    u'"AiiDA: automated interactive infrastructure and database for computational science", '
    u'Comp. Mat. Sci 111, 218-230 (2016); https://doi.org/10.1016/j.commatsci.2015.09.013 '
    u'- http://www.aiida.net.')
__paper_short__ = 'G. Pizzi et al., Comp. Mat. Sci 111, 218 (2016).'

# Configure the default logging
configure_logging()

if get_config_option('warnings.showdeprecations'):
    # If the user does not want to get AiiDA deprecation warnings, we disable them - this can be achieved with::
    #   verdi config warnings.showdeprecations False
    # Note that the AiidaDeprecationWarning does NOT inherit from DeprecationWarning
    warnings.simplefilter('default', AiidaDeprecationWarning)  # pylint: disable=no-member
    # This should default to 'once', i.e. once per different message
else:
    warnings.simplefilter('ignore', AiidaDeprecationWarning)  # pylint: disable=no-member

if six.PY2:
    warnings.warn('python 2 will be deprecated in `aiida-core v2.0.0`',
                  DeprecationWarning)  # pylint: disable=no-member

Пример #12
0
def fixture_environment():
    """Setup a complete AiiDA test environment, with configuration, profile, database and repository."""
    with fixture_manager() as manager:
        from aiida.common.log import configure_logging
        configure_logging(with_orm=True)
        yield manager
Пример #13
0
def tick_work():
    configure_logging(daemon=True, daemon_log_file=DAEMON_LOG_FILE)
    from aiida.work.daemon import tick_workflow_engine
    LOGGER.info('Ticking workflows')
    tick_workflow_engine()