示例#1
0
    def _get_repository_path(self):
        from aiida.backends import settings
        from aiida.common.setup import (get_config, get_profile_config,
                                        parse_repository_uri)
        from aiida.common.exceptions import ConfigurationError

        try:
            confs = get_config()
        except ConfigurationError:
            raise ConfigurationError(
                "Please run the AiiDA Installation, no config found")

        if settings.AIIDADB_PROFILE is None:
            raise ConfigurationError(
                "settings.AIIDADB_PROFILE not defined, did you load django"
                "through the AiiDA load_dbenv()?")

        profile_conf = get_profile_config(settings.AIIDADB_PROFILE,
                                          conf_dict=confs)

        REPOSITORY_URI = profile_conf.get('AIIDADB_REPOSITORY_URI', '')
        REPOSITORY_PROTOCOL, REPOSITORY_PATH = parse_repository_uri(
            REPOSITORY_URI)

        return REPOSITORY_PATH
示例#2
0
文件: lsf.py 项目: zhonger/aiida-core
    def __init__(self, **kwargs):
        """
        Initialize the job resources from the passed arguments (the valid keys can be
        obtained with the function self.get_valid_keys()).

        :raise ValueError: on invalid parameters.
        :raise TypeError: on invalid parameters.
        :raise aiida.common.ConfigurationError: if default_mpiprocs_per_machine was set for this
            computer, since LsfJobResource cannot accept this parameter.
        """
        from aiida.common.exceptions import ConfigurationError
        super().__init__()

        self.parallel_env = kwargs.pop('parallel_env', '')
        if not isinstance(self.parallel_env, str):
            raise TypeError("When specified, 'parallel_env' must be a string")

        try:
            self.tot_num_mpiprocs = int(kwargs.pop('tot_num_mpiprocs'))
        except (KeyError, ValueError) as exc:
            raise TypeError('tot_num_mpiprocs must be specified and must be an integer') from exc

        default_mpiprocs_per_machine = kwargs.pop('default_mpiprocs_per_machine', None)
        if default_mpiprocs_per_machine is not None:
            raise ConfigurationError('default_mpiprocs_per_machine cannot be set for LSF scheduler')

        num_machines = kwargs.pop('num_machines', None)
        if num_machines is not None:
            raise ConfigurationError('num_machines cannot be set for LSF scheduler')

        if self.tot_num_mpiprocs <= 0:
            raise ValueError('tot_num_mpiprocs must be >= 1')
示例#3
0
def get_dbauthinfo(computer, aiidauser):
    """
    Given a computer and a user, returns a DbAuthInfo object

    :param computer: a computer (can be a string, Computer or DbComputer instance)
    :param aiidauser: a user, can be a DbUser or a User instance
    :return: a DbAuthInfo instance
    :raise NotExistent: if the user is not configured to use computer
    :raise sqlalchemy.orm.exc.MultipleResultsFound: if the user is configured 
         more than once to use the computer! Should never happen
    """
    from aiida.common.exceptions import InternalError
    if settings.BACKEND == BACKEND_DJANGO:
        from aiida.backends.djsite.db.models import DbComputer, DbAuthInfo, DbUser
        from django.core.exceptions import (ObjectDoesNotExist,
                                            MultipleObjectsReturned)

        try:
            authinfo = DbAuthInfo.objects.get(
                # converts from name, Computer or DbComputer instance to
                # a DbComputer instance
                dbcomputer=DbComputer.get_dbcomputer(computer),
                aiidauser=aiidauser.id)
        except ObjectDoesNotExist:
            raise NotExistent(
                "The aiida user {} is not configured to use computer {}".
                format(aiidauser.email, computer.name))
        except MultipleObjectsReturned:
            raise ConfigurationError(
                "The aiida user {} is configured more than once to use "
                "computer {}! Only one configuration is allowed".format(
                    aiidauser.email, computer.name))
    elif settings.BACKEND == BACKEND_SQLA:

        from aiida.backends.sqlalchemy.models.authinfo import DbAuthInfo
        from aiida.backends.sqlalchemy import get_scoped_session
        session = get_scoped_session()
        from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound

        try:
            authinfo = session.query(DbAuthInfo).filter_by(
                dbcomputer_id=computer.id,
                aiidauser_id=aiidauser.id,
            ).one()
        except NoResultFound:
            raise NotExistent(
                "The aiida user {} is not configured to use computer {}".
                format(aiidauser.email, computer.name))
        except MultipleResultsFound:
            raise ConfigurationError(
                "The aiida user {} is configured more than once to use "
                "computer {}! Only one configuration is allowed".format(
                    aiidauser.email, computer.name))

    else:
        raise InternalError("unknown backend {}".format(settings.BACKEND))
    return authinfo
示例#4
0
def get_db_test_list():
    """
    This function returns the db_test_list for the current backend,
    merged with the 'common' tests.

    :note: This function should be called only after setting the
      backend, and then it returns only the tests for this backend, and the common ones.
    """
    from aiida.backends import settings
    from aiida.common.exceptions import ConfigurationError
    from collections import defaultdict

    current_backend = settings.BACKEND
    try:
        be_tests = db_test_list[current_backend]
    except KeyError:
        raise ConfigurationError("No backend configured yet")

    # Could be undefined, so put to empty dict by default
    try:
        common_tests = db_test_list["common"]
    except KeyError:
        raise ConfigurationError("A 'common' key must always be defined!")

    retdict = defaultdict(list)
    for k, tests in common_tests.iteritems():
        for t in tests:
            retdict[k].append(t)
    for k, tests in be_tests.iteritems():
        for t in tests:
            retdict[k].append(t)

    # This is a temporary solution to be able to run tests in plugins. Once the plugin fixtures
    # have been made working and are released, we can replace this logic with them
    for ep in [ep for ep in epm.iter_entry_points(group='aiida.tests')]:
        retdict[ep.name].append(ep.module_name)

    # Explode the dictionary so that if I have a.b.c,
    # I can run it also just with 'a' or with 'a.b'
    final_retdict = defaultdict(list)
    for k, v in retdict.iteritems():
        final_retdict[k] = v
    for k, v in retdict.iteritems():
        if '.' in k:
            parts = k.split('.')
            for last_idx in range(1, len(parts)):
                parentkey = ".".join(parts[:last_idx])
                final_retdict[parentkey].extend(v)

    return dict(final_retdict)
示例#5
0
 def table2resource(table_name):
     # TODO Consider ways to make this function backend independent (one
     # idea would be to go from table name to aiida class name which is
     # univoque)
     if BACKEND == BACKEND_DJANGO:
         (spam, resource_name) = issingular(table_name[2:].lower())
     elif BACKEND == BACKEND_SQLA:
         (spam, resource_name) = issingular(table_name[5:])
     elif BACKEND is None:
         raise ConfigurationError("settings.BACKEND has not been set.\n"
                                  "Hint: Have you called "
                                  "aiida.load_dbenv?")
     else:
         raise ConfigurationError("Unknown settings.BACKEND: {}".format(
             BACKEND))
     return resource_name
示例#6
0
def run_migrations_online():
    """Run migrations in 'online' mode.

    The connection should have been passed to the config, which we use to configue the migration context.
    """

    # pylint: disable=unused-import
    from aiida.backends.sqlalchemy.models.authinfo import DbAuthInfo
    from aiida.backends.sqlalchemy.models.comment import DbComment
    from aiida.backends.sqlalchemy.models.computer import DbComputer
    from aiida.backends.sqlalchemy.models.group import DbGroup
    from aiida.backends.sqlalchemy.models.log import DbLog
    from aiida.backends.sqlalchemy.models.node import DbLink, DbNode
    from aiida.backends.sqlalchemy.models.settings import DbSetting
    from aiida.backends.sqlalchemy.models.user import DbUser
    from aiida.common.exceptions import DbContentError
    from aiida.backends.sqlalchemy.models.base import Base
    config = context.config  # pylint: disable=no-member

    connectable = config.attributes.get('connection', None)

    if connectable is None:
        from aiida.common.exceptions import ConfigurationError
        raise ConfigurationError(
            'An initialized connection is expected for the AiiDA online migrations.'
        )

    with connectable.connect() as connection:
        context.configure(  # pylint: disable=no-member
            connection=connection,
            target_metadata=Base.metadata,
            transaction_per_migration=True,
        )

        context.run_migrations()  # pylint: disable=no-member
示例#7
0
def _get_config(config_file):
    try:
        with open(config_file, 'r') as f:
            config = yaml.load(f)[get_current_profile()]
    # no config file, or no config for this profile
    except (OSError, IOError, KeyError):
        return DEFAULT_CONFIG

    # validate configuration
    for key in config:
        if key not in DEFAULT_CONFIG:
            raise ValueError(
                "Configuration error: Invalid key '{}' in cache_config.yml".format(key)
            )

    # add defaults where config is missing
    for key, default_config in DEFAULT_CONFIG.items():
        config[key] = config.get(key, default_config)

    # load classes
    try:
        for key in [config_keys.enabled, config_keys.disabled]:
            config[key] = [load_class(c) for c in config[key]]
    except (ImportError, ClassNotFoundException) as err:
        raise_from(
            ConfigurationError("Unknown class given in 'cache_config.yml': '{}'".format(err)),
            err
        )
    return config
示例#8
0
def check_schema_version(profile_name):
    """
    Check if the version stored in the database is the same of the version of the code.

    :raise aiida.common.ConfigurationError: if the two schema versions do not match
    """
    from aiida.backends import sqlalchemy as sa
    from aiida.common.exceptions import ConfigurationError

    alembic_cfg = get_alembic_conf()

    validate_schema_generation()

    # Getting the version of the code and the database, reusing the existing engine (initialized by AiiDA)
    with sa.ENGINE.begin() as connection:
        alembic_cfg.attributes['connection'] = connection
        code_schema_version = get_migration_head(alembic_cfg)
        db_schema_version = get_db_schema_version(alembic_cfg)

    if code_schema_version != db_schema_version:
        raise ConfigurationError(
            'Database schema version {} is outdated compared to the code schema version {}\n'
            'Before you upgrade, make sure all calculations and workflows have finished running.\n'
            'If this is not the case, revert the code to the previous version and finish them first.\n'
            'To migrate the database to the current version, run the following commands:'
            '\n  verdi -p {} daemon stop\n  verdi -p {} database migrate'.
            format(db_schema_version, code_schema_version, profile_name,
                   profile_name))
示例#9
0
def run_migrations_online():
    """Run migrations in 'online' mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.

    """
    # This is the Alembic Config object, which provides
    # access to the values within the .ini file in use.
    # It is initialized by alembic and we enrich it here
    # to point to the right database configuration.
    config = context.config

    connectable = config.attributes.get('connection', None)

    if connectable is None:
        from aiida.common.exceptions import ConfigurationError
        raise ConfigurationError("An initialized connection is expected "
                                 "for the AiiDA online migrations.")

    with connectable.connect() as connection:
        context.configure(connection=connection,
                          target_metadata=target_metadata)

        with context.begin_transaction():
            context.run_migrations()
示例#10
0
def get_repository_folder(subfolder=None):
    """
    Return the top folder of the local repository.
    """
    try:
        return _repository_folder_cache[subfolder]
    except KeyError:
        try:
            from aiida.settings import REPOSITORY_PATH

            if not os.path.isdir(REPOSITORY_PATH):
                raise ImportError
        except ImportError:
            raise ConfigurationError(
                "The REPOSITORY_PATH variable is not set correctly.")
        if subfolder is None:
            retval = os.path.abspath(REPOSITORY_PATH)
        elif subfolder == "sandbox":
            retval = os.path.abspath(os.path.join(REPOSITORY_PATH, 'sandbox'))
        elif subfolder == "repository":
            retval = os.path.abspath(
                os.path.join(REPOSITORY_PATH, 'repository'))
        else:
            raise ValueError("Invalid 'subfolder' passed to "
                             "get_repository_folder: {}".format(subfolder))
        _repository_folder_cache[subfolder] = retval
        return retval
示例#11
0
 def get_transport_class(self):
     try:
         # I return the class, not an instance
         return TransportFactory(self.get_transport_type())
     except MissingPluginError as e:
         raise ConfigurationError('No transport found for {} [type {}], message: {}'.format(
             self.name, self.get_transport_type(), e.message))
示例#12
0
    def get_backend_class(cls):
        """Get backend class."""
        from aiida.backends.testimplbase import AiidaTestImplementation
        from aiida.backends import BACKEND_SQLA, BACKEND_DJANGO
        from aiida.manage.configuration import PROFILE

        # Freeze the __impl_class after the first run
        if not hasattr(cls, '__impl_class'):
            if PROFILE.database_backend == BACKEND_SQLA:
                from aiida.backends.sqlalchemy.testbase import SqlAlchemyTests
                cls.__impl_class = SqlAlchemyTests
            elif PROFILE.database_backend == BACKEND_DJANGO:
                from aiida.backends.djsite.db.testbase import DjangoTests
                cls.__impl_class = DjangoTests
            else:
                raise ConfigurationError('Unknown backend type')

            # Check that it is of the right class
            if not issubclass(cls.__impl_class, AiidaTestImplementation):
                raise InternalError(
                    'The AiiDA test implementation is not of type '
                    '{}, that is not a subclass of AiidaTestImplementation'.
                    format(cls.__impl_class.__name__))

        return cls.__impl_class
示例#13
0
    def __init__(self, **kwargs):
        """
        Initialize the job resources from the passed arguments (the valid keys can be
        obtained with the function self.get_valid_keys()).

        :raise ValueError: on invalid parameters.
        :raise TypeError: on invalid parameters.
        :raise ConfigurationError: if default_mpiprocs_per_machine was set for this
            computer, since ParEnvJobResource cannot accept this parameter.
        """
        from aiida.common.exceptions import ConfigurationError

        try:
            self.parallel_env = str(kwargs.pop('parallel_env'))
        except (KeyError, TypeError, ValueError):
            raise TypeError("'parallel_env' must be specified and must be a string")

        try:
            self.tot_num_mpiprocs = int(kwargs.pop('tot_num_mpiprocs'))
        except (KeyError, ValueError):
            raise TypeError("tot_num_mpiprocs must be specified and must be an integer")

        default_mpiprocs_per_machine = kwargs.pop('default_mpiprocs_per_machine', None)
        if default_mpiprocs_per_machine is not None:
            raise ConfigurationError("default_mpiprocs_per_machine cannot be set "
                                     "for schedulers that use ParEnvJobResource")

        if self.tot_num_mpiprocs <= 0:
            raise ValueError("tot_num_mpiprocs must be >= 1")
示例#14
0
    def get_schema(self):

        # Construct the full class string
        class_string = 'aiida.orm.' + self._aiida_type

        # Load correspondent orm class
        orm_class = get_object_from_string(class_string)

        # Construct the json object to be returned
        basic_schema = orm_class.get_schema()

        schema = {}
        ordering = []

        # get addional info and column order from translator class
        # and combine it with basic schema
        if len(self._schema_projections["column_order"]) > 0:
            for field in self._schema_projections["column_order"]:

                # basic schema
                if field in basic_schema.keys():
                    schema[field] = basic_schema[field]
                else:
                    ## Note: if column name starts with user_* get the schema information from
                    # user class. It is added mainly to handle user_email case.
                    # TODO need to improve
                    field_parts = field.split("_")
                    if field_parts[0] == "user" and field != "user_id" and len(
                            field_parts) > 1:
                        from aiida.orm.user import User
                        user_schema = User.get_schema()
                        if field_parts[1] in user_schema.keys():
                            schema[field] = user_schema[field_parts[1]]
                        else:
                            raise KeyError(
                                "{} is not present in user schema".format(
                                    field))
                    else:
                        raise KeyError(
                            "{} is not present in ORM basic schema".format(
                                field))

                # additional info defined in translator class
                if field in self._schema_projections["additional_info"]:
                    schema[field].update(
                        self._schema_projections["additional_info"][field])
                else:
                    raise KeyError(
                        "{} is not present in default projection additional info"
                        .format(field))

            # order
            ordering = self._schema_projections["column_order"]

        else:
            raise ConfigurationError(
                "Define column order to get schema for {}".format(
                    self._aiida_type))

        return dict(fields=schema, ordering=ordering)
示例#15
0
def load_dbenv(process=None, profile=None, *args, **kwargs):
    if is_dbenv_loaded():
        raise InvalidOperation("You cannot call load_dbenv multiple times!")
    settings.LOAD_DBENV_CALLED = True

    # This is going to set global variables in settings, including
    # settings.BACKEND
    load_profile(process=process, profile=profile)

    if settings.BACKEND == BACKEND_SQLA:
        # Maybe schema version should be also checked for SQLAlchemy version.
        from aiida.backends.sqlalchemy.utils \
            import load_dbenv as load_dbenv_sqlalchemy
        return load_dbenv_sqlalchemy(process=process,
                                     profile=profile,
                                     *args,
                                     **kwargs)
    elif settings.BACKEND == BACKEND_DJANGO:
        from aiida.backends.djsite.utils import load_dbenv as load_dbenv_django
        return load_dbenv_django(process=process,
                                 profile=profile,
                                 *args,
                                 **kwargs)
    else:
        raise ConfigurationError("Invalid settings.BACKEND: {}".format(
            settings.BACKEND))
示例#16
0
 def get_scheduler(self):
     try:
         ThisPlugin = SchedulerFactory(self.get_scheduler_type())
         # I call the init without any parameter
         return ThisPlugin()
     except MissingPluginError as e:
         raise ConfigurationError('No scheduler found for {} [type {}], message: {}'.format(
             self.name, self.get_scheduler_type(), e.message))
示例#17
0
def get_authinfo(computer, aiidauser):

    if settings.BACKEND == BACKEND_DJANGO:
        from aiida.backends.djsite.db.models import DbComputer, DbAuthInfo
        from django.core.exceptions import (ObjectDoesNotExist,
                                            MultipleObjectsReturned)

        try:
            authinfo = DbAuthInfo.objects.get(
                # converts from name, Computer or DbComputer instance to
                # a DbComputer instance
                dbcomputer=DbComputer.get_dbcomputer(computer),
                aiidauser=aiidauser)
        except ObjectDoesNotExist:
            raise AuthenticationError(
                "The aiida user {} is not configured to use computer {}".
                format(aiidauser.email, computer.name))
        except MultipleObjectsReturned:
            raise ConfigurationError(
                "The aiida user {} is configured more than once to use "
                "computer {}! Only one configuration is allowed".format(
                    aiidauser.email, computer.name))
    elif settings.BACKEND == BACKEND_SQLA:
        from aiida.backends.sqlalchemy.models.authinfo import DbAuthInfo
        from aiida.backends.sqlalchemy import get_scoped_session
        session = get_scoped_session()
        from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
        try:
            authinfo = session.query(DbAuthInfo).filter_by(
                dbcomputer_id=computer.id,
                aiidauser_id=aiidauser.id,
            ).one()
        except NoResultFound:
            raise AuthenticationError(
                "The aiida user {} is not configured to use computer {}".
                format(aiidauser.email, computer.name))
        except MultipleResultsFound:
            raise ConfigurationError(
                "The aiida user {} is configured more than once to use "
                "computer {}! Only one configuration is allowed".format(
                    aiidauser.email, computer.name))

    else:
        raise Exception("unknown backend {}".format(settings.BACKEND))
    return authinfo
示例#18
0
def get_db_test_list():
    """
    This function returns the db_test_list for the current backend, 
    merged with the 'common' tests.

    :note: This function should be called only after setting the
      backend, and then it returns only the tests for this backend, and the common ones.
    """
    from aiida.backends import settings
    from aiida.common.exceptions import ConfigurationError
    from collections import defaultdict

    current_backend = settings.BACKEND
    try:
        be_tests = db_test_list[current_backend]
    except KeyError:
        raise ConfigurationError("No backend configured yet")

    # Could be undefined, so put to empty dict by default
    try:
        common_tests = db_test_list["common"]
    except KeyError:
        raise ConfigurationError("A 'common' key must always be defined!")

    retdict = defaultdict(list)
    for k, tests in common_tests.iteritems():
        for t in tests:
            retdict[k].append(t)
    for k, tests in be_tests.iteritems():
        for t in tests:
            retdict[k].append(t)

    # Explode the dictionary so that if I have a.b.c,
    # I can run it also just with 'a' or with 'a.b'
    final_retdict = defaultdict(list)
    for k, v in retdict.iteritems():
        final_retdict[k] = v
    for k, v in retdict.iteritems():
        if '.' in k:
            parts = k.split('.')
            for last_idx in range(1, len(parts)):
                parentkey = ".".join(parts[:last_idx])
                final_retdict[parentkey].extend(v)

    return dict(final_retdict)
示例#19
0
def QueryFactory():
    if settings.BACKEND == BACKEND_SQLA:
        from aiida.backends.sqlalchemy.queries import QueryManagerSQLA as QueryManager
    elif settings.BACKEND == BACKEND_DJANGO:
        from aiida.backends.djsite.queries import QueryManagerDjango as QueryManager
    else:
        raise ConfigurationError("Invalid settings.BACKEND: {}".format(
            settings.BACKEND))
    return QueryManager
示例#20
0
 def cmd_string(self):
     """
     Return the command string to start the AiiDA daemon
     """
     from aiida.common.exceptions import ConfigurationError
     if VERDI_BIN is None:
         raise ConfigurationError("Unable to find 'verdi' in the path. Make sure that you are working "
             "in a virtual environment, or that at least the 'verdi' executable is on the PATH")
     return '{} -p {} devel run_daemon'.format(VERDI_BIN, self.profile_name)
示例#21
0
def get_db_test_list():
    """
    This function returns the DB_TEST_LIST for the current backend,
    merged with the 'common' tests.

    :note: This function should be called only after setting the
      backend, and then it returns only the tests for this backend, and the common ones.
    """
    from collections import defaultdict
    from aiida.common.exceptions import ConfigurationError
    from aiida.manage import configuration

    try:
        be_tests = DB_TEST_LIST[configuration.PROFILE.database_backend]
    except KeyError:
        raise ConfigurationError('No backend configured yet')

    # Could be undefined, so put to empty dict by default
    try:
        common_tests = DB_TEST_LIST['common']
    except KeyError:
        raise ConfigurationError("A 'common' key must always be defined!")

    retdict = defaultdict(list)
    for k, tests in common_tests.items():
        for test in tests:
            retdict[k].append(test)
    for k, tests in be_tests.items():
        for test in tests:
            retdict[k].append(test)

    # Explode the dictionary so that if I have a.b.c,
    # I can run it also just with 'a' or with 'a.b'
    final_retdict = defaultdict(list)
    for key, val in retdict.items():
        final_retdict[key] = val
    for key, val in retdict.items():
        if '.' in key:
            parts = key.split('.')
            for last_idx in range(1, len(parts)):
                parentkey = '.'.join(parts[:last_idx])
                final_retdict[parentkey].extend(val)

    return dict(final_retdict)
示例#22
0
def get_profiles_list():
    """
    Return the list of names of installed configurations
    """
    from aiida.common.exceptions import ConfigurationError

    all_config = get_config()
    try:
        return all_config['profiles'].keys()
    except KeyError:
        return ConfigurationError("Please run the setup")
示例#23
0
def parse_repository_uri(repository_uri):
    """
    This function validates the REPOSITORY_URI, that should be in the
    format protocol://address

    :note: At the moment, only the file protocol is supported.

    :return: a tuple (protocol, address).
    """
    import uritools
    parts = uritools.urisplit(repository_uri)

    if parts.scheme != u'file':
        raise ConfigurationError("The current AiiDA version supports only a "
                                 "local repository")

    if parts.scheme == u'file':
        if not os.path.isabs(parts.path):
            raise ConfigurationError("The current repository is specified with a "
                                     "file protocol but with a relative path")

        # Normalize path to its absolute path
        return parts.scheme, os.path.expanduser(parts.path)
示例#24
0
        def table2resource(table_name):
            """
            Convert the related_tablevalues to the RESTAPI resources
            (orm class/db table ==> RESTapi resource)

            :param table_name (str): name of the table (in SQLA is __tablename__)
            :return: resource_name (str): name of the API resource
            """
            # TODO Consider ways to make this function backend independent (one
            # idea would be to go from table name to aiida class name which is
            # unique)
            if BACKEND == BACKEND_DJANGO:
                (spam, resource_name) = issingular(table_name[2:].lower())
            elif BACKEND == BACKEND_SQLA:
                (spam, resource_name) = issingular(table_name[5:])
            elif BACKEND is None:
                raise ConfigurationError("settings.BACKEND has not been set.\n"
                                         "Hint: Have you called "
                                         "aiida.load_dbenv?")
            else:
                raise ConfigurationError(
                    "Unknown settings.BACKEND: {}".format(BACKEND))
            return resource_name
示例#25
0
def load_dbenv(profile=None, *args, **kwargs):
    if configuration.PROFILE.database_backend == BACKEND_SQLA:
        # Maybe schema version should be also checked for SQLAlchemy version.
        from aiida.backends.sqlalchemy.utils \
            import load_dbenv as load_dbenv_sqlalchemy
        to_return = load_dbenv_sqlalchemy(profile=profile, *args, **kwargs)
    elif configuration.PROFILE.database_backend == BACKEND_DJANGO:
        from aiida.backends.djsite.utils import load_dbenv as load_dbenv_django
        to_return = load_dbenv_django(profile=profile, *args, **kwargs)
    else:
        raise ConfigurationError(
            'Invalid configuration.PROFILE.database_backend: {}'.format(
                configuration.PROFILE.database_backend))

    return to_return
示例#26
0
def validate_schema_generation():
    """Verify that the database schema generation is compatible with the current code schema generation."""
    from aiida.common.exceptions import ConfigurationError, NotExistent
    try:
        schema_generation_database = get_db_schema_generation().value
    except NotExistent:
        schema_generation_database = '1'

    if schema_generation_database is None:
        schema_generation_database = '1'

    if schema_generation_database != SCHEMA_GENERATION_VALUE:
        raise ConfigurationError(
            'The schema generation of your database {} is newer than that of the code `{}` and is incompatible.'
            .format(schema_generation_database, SCHEMA_GENERATION_VALUE))
示例#27
0
def parse_repository_uri(repository_uri):
    """
    This function validates the REPOSITORY_URI, that should be in the
    format protocol://address

    :note: At the moment, only the file protocol is supported.

    :return: a tuple (protocol, address).
    """

    protocol, _, address = repository_uri.partition('://')

    if protocol != 'file':
        raise ConfigurationError("The current AiiDA version supports only a "
                                 "local repository")

    if protocol == 'file':
        if not os.path.isabs(address):
            raise ConfigurationError("The current repository is specified with a "
                                     "file protocol but with a relative path")
        address = os.path.expanduser(address)

    # Normalize address to its absolute path
    return (protocol, address)
示例#28
0
def get_automatic_user():
    # global _aiida_autouser_cache

    # if _aiida_autouser_cache is not None:
    #     return _aiida_autouser_cache

    from aiida.backends.sqlalchemy.models.user import DbUser
    from aiida.common.utils import get_configured_user_email

    email = get_configured_user_email()

    _aiida_autouser_cache = DbUser.query.filter(DbUser.email == email).first()

    if not _aiida_autouser_cache:
        raise ConfigurationError("No aiida user with email {}".format(email))
    return _aiida_autouser_cache
示例#29
0
    def get_transport(self):
        """
        Return a configured transport to connect to the computer.
        """
        computer = self.computer
        try:
            ThisTransport = TransportFactory(computer.get_transport_type())
        except MissingPluginError as e:
            raise ConfigurationError(
                'No transport found for {} [type {}], message: {}'.format(
                    computer.hostname, computer.get_transport_type(),
                    e.message))

        params = dict(computer.get_transport_params().items() +
                      self.get_auth_params().items())
        return ThisTransport(machine=computer.hostname, **params)
示例#30
0
def check_schema_version():
    """
    Check if the version stored in the database is the same of the version
    of the code.

    :note: if the DbSetting table does not exist, this function does not
      fail. The reason is to avoid to have problems before running the first
      migrate call.

    :note: if no version is found, the version is set to the version of the
      code. This is useful to have the code automatically set the DB version
      at the first code execution.

    :raise ConfigurationError: if the two schema versions do not match.
      Otherwise, just return.
    """
    import os
    import aiida.backends.djsite.db.models
    from aiida.backends.utils import get_current_profile
    from django.db import connection
    from aiida.common.exceptions import ConfigurationError

    # Do not do anything if the table does not exist yet
    if 'db_dbsetting' not in connection.introspection.table_names():
        return

    code_schema_version = aiida.backends.djsite.db.models.SCHEMA_VERSION
    db_schema_version = get_db_schema_version()

    if db_schema_version is None:
        # No code schema defined yet, I set it to the code version
        set_db_schema_version(code_schema_version)
        db_schema_version = get_db_schema_version()

    filepath_utils = os.path.abspath(__file__)
    filepath_manage = os.path.join(os.path.dirname(filepath_utils),
                                   'manage.py')

    if code_schema_version != db_schema_version:
        raise ConfigurationError(
            "The code schema version is {}, but the version stored in the "
            "database (DbSetting table) is {}, stopping.\n"
            "To migrate the database to the current version, run the following commands:"
            "\n  verdi daemon stop\n  python {} --aiida-profile={} migrate".
            format(code_schema_version, db_schema_version, filepath_manage,
                   get_current_profile()))