Ejemplo n.º 1
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))
Ejemplo n.º 2
0
def transition_load_db_env(process=None, profile=None, *args, **kwargs):
    from aiida.backends.profile import load_profile
    from aiida.backends import settings
    from aiida.backends.sqlalchemy.utils import _load_dbenv_noschemacheck

    settings.LOAD_DBENV_CALLED = True

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

    _load_dbenv_noschemacheck(process=process, profile=profile)
Ejemplo n.º 3
0
def setup(profile, only_config, non_interactive=False, **kwargs):
    '''
    setup an aiida profile and aiida user (and the aiida default user).

    :param profile: Profile name
    :param only_config: do not create a new user
    :param non_interactive: do not prompt for configuration values, fail if not all values are given as kwargs.
    :param backend: one of 'django', 'sqlalchemy'
    :param email: valid email address for the user
    :param db_host: hostname for the database
    :param db_port: port to connect to the database
    :param db_user: name of the db user
    :param db_pass: password of the db user
    '''
    from aiida.common.setup import (create_base_dirs, create_configuration,
                                    set_default_profile, DEFAULT_UMASK,
                                    create_config_noninteractive)
    from aiida.backends.profile import BACKEND_SQLA, BACKEND_DJANGO
    from aiida.backends.utils import set_backend_type
    from aiida.common.exceptions import InvalidOperation

    # ~ cmdline_args = list(args)

    # ~ only_user_config = False
    # ~ try:
    # ~ cmdline_args.remove('--only-config')
    # ~ only_user_config = True
    # ~ except ValueError:
    # ~ # Parameter not provided
    # ~ pass
    only_user_config = only_config

    # ~ if cmdline_args:
    # ~ print >> sys.stderr, "Unknown parameters on the command line: "
    # ~ print >> sys.stderr, ", ".join(cmdline_args)
    # ~ sys.exit(1)

    # create the directories to store the configuration files
    create_base_dirs()
    # gprofile = 'default' if profile is None else profile
    # ~ gprofile = profile if settings_profile.AIIDADB_PROFILE is None \
    # ~ else settings_profile.AIIDADB_PROFILE
    if settings_profile.AIIDADB_PROFILE and profile:
        sys.exit(
            'the profile argument cannot be used if verdi is called with -p option: {} and {}'
            .format(settings_profile.AIIDADB_PROFILE, profile))
    gprofile = settings_profile.AIIDADB_PROFILE or profile
    if gprofile == profile:
        settings_profile.AIIDADB_PROFILE = profile
    if not settings_profile.AIIDADB_PROFILE:
        settings_profile.AIIDADB_PROFILE = 'default'

    # used internally later
    gprofile = settings_profile.AIIDADB_PROFILE

    created_conf = None
    # ask and store the configuration of the DB
    if non_interactive:
        try:
            created_conf = create_config_noninteractive(
                profile=gprofile,
                backend=kwargs['backend'],
                email=kwargs['email'],
                db_host=kwargs['db_host'],
                db_port=kwargs['db_port'],
                db_name=kwargs['db_name'],
                db_user=kwargs['db_user'],
                db_pass=kwargs.get('db_pass', ''),
                repo=kwargs['repo'],
                force_overwrite=kwargs.get('force_overwrite', False))
        except ValueError as e:
            click.echo("Error during configuation: {}".format(e.message),
                       err=True)
            sys.exit(1)
        except KeyError as e:
            click.echo(
                "--non-interactive requires all values to be given on the commandline! Missing argument: {}"
                .format(e.message),
                err=True)
            sys.exit(1)
    else:
        try:
            created_conf = create_configuration(profile=gprofile)
        except ValueError as e:
            print >> sys.stderr, "Error during configuration: {}".format(
                e.message)
            sys.exit(1)

        # set default DB profiles
        set_default_profile('verdi', gprofile, force_rewrite=False)
        set_default_profile('daemon', gprofile, force_rewrite=False)

    if only_user_config:
        print(
            "Only user configuration requested, "
            "skipping the migrate command")
    else:
        print "Executing now a migrate command..."

        backend_choice = created_conf['AIIDADB_BACKEND']
        if backend_choice == BACKEND_DJANGO:
            print("...for Django backend")
            # The correct profile is selected within load_dbenv.
            # Setting os.umask here since sqlite database gets created in
            # this step.
            old_umask = os.umask(DEFAULT_UMASK)

            # This check should be done more properly
            # try:
            #     backend_type = get_backend_type()
            # except KeyError:
            #     backend_type = None
            #
            # if backend_type is not None and backend_type != BACKEND_DJANGO:
            #     raise InvalidOperation("An already existing database found"
            #                            "and a different than the selected"
            #                            "backend was used for its "
            #                            "management.")

            try:
                pass_to_django_manage([execname, 'migrate'], profile=gprofile)
            finally:
                os.umask(old_umask)

            set_backend_type(BACKEND_DJANGO)

        elif backend_choice == BACKEND_SQLA:
            print("...for SQLAlchemy backend")
            from aiida import is_dbenv_loaded
            from aiida.backends import settings
            from aiida.backends.sqlalchemy.utils import (
                _load_dbenv_noschemacheck, check_schema_version)
            from aiida.backends.profile import load_profile

            # We avoid calling load_dbenv since we want to force the schema
            # migration
            if not is_dbenv_loaded():
                settings.LOAD_DBENV_CALLED = True
                # This is going to set global variables in settings, including
                # settings.BACKEND
                load_profile()
                _load_dbenv_noschemacheck()

            # Perform the needed migration quietly
            check_schema_version(force_migration=True)
            set_backend_type(BACKEND_SQLA)

        else:
            raise InvalidOperation("Not supported backend selected.")

    print "Database was created successfully"

    # I create here the default user
    print "Loading new environment..."
    if only_user_config:
        from aiida.backends.utils import load_dbenv, is_dbenv_loaded
        # db environment has not been loaded in this case
        if not is_dbenv_loaded():
            load_dbenv()

    from aiida.common.setup import DEFAULT_AIIDA_USER
    from aiida.orm.user import User as AiiDAUser

    if not AiiDAUser.search_for_users(email=DEFAULT_AIIDA_USER):
        print "Installing default AiiDA user..."
        nuser = AiiDAUser(email=DEFAULT_AIIDA_USER)
        nuser.first_name = "AiiDA"
        nuser.last_name = "Daemon"
        nuser.is_staff = True
        nuser.is_active = True
        nuser.is_superuser = True
        nuser.force_save()

    from aiida.common.utils import get_configured_user_email
    email = get_configured_user_email()
    print "Starting user configuration for {}...".format(email)
    if email == DEFAULT_AIIDA_USER:
        print "You set up AiiDA using the default Daemon email ({}),".format(
            email)
        print "therefore no further user configuration will be asked."
    else:
        # Ask to configure the new user
        if not non_interactive:
            user.configure.main(args=[email])
        else:
            # or don't ask
            aiida.cmdline.commands.user.do_configure(
                email=kwargs['email'],
                first_name=kwargs.get('first_name'),
                last_name=kwargs.get('last_name'),
                institution=kwargs.get('institution'),
                no_password=True,
                non_interactive=non_interactive,
                force=True)

    print "Setup finished."
Ejemplo n.º 4
0
    args = parser.parse_args()

    if args.backend != "sqlalchemy" and (args.gin_index
                                         or args.delete_gin_index):
        raise parser.error("You can't use a GIN index with Django.")

    if args.bprofile:
        from bprofile import BProfile
        profiler = lambda: BProfile(args.bprofile)
    else:
        from contextlib import contextmanager
        # noop context manager
        profiler = contextmanager(lambda: (yield))

    profile = args.profile or profiles[args.backend]
    load_profile(profile=profile)

    from aiida.backends.utils import load_dbenv
    load_dbenv()

    # XXX remove this and use the profile to decide which backend to use
    if args.backend == "django":
        from dj import queries
    else:
        from sqla import queries, create_gin_index, delete_gin_index
        from aiida.backends import sqlalchemy

    if args.delete_gin_index:
        print('Deleting GIN index on attributes..')
        delete_gin_index()
    if args.gin_index:
Ejemplo n.º 5
0
def setup_profile(profile,
                  only_config,
                  set_default=False,
                  non_interactive=False,
                  **kwargs):
    """
    Setup an AiiDA profile and AiiDA user (and the AiiDA default user).

    :param profile: Profile name
    :param only_config: do not create a new user
    :param set_default: set the new profile as the default
    :param non_interactive: do not prompt for configuration values, fail if not all values are given as kwargs.
    :param backend: one of 'django', 'sqlalchemy'
    :param email: valid email address for the user
    :param db_host: hostname for the database
    :param db_port: port to connect to the database
    :param db_user: name of the db user
    :param db_pass: password of the db user
    """
    from aiida.backends import settings
    from aiida.backends.profile import BACKEND_SQLA, BACKEND_DJANGO
    from aiida.backends.utils import set_backend_type
    from aiida.cmdline import EXECNAME
    from aiida.cmdline.commands import cmd_user
    from aiida.common.exceptions import InvalidOperation
    from aiida.common.setup import (create_base_dirs, create_configuration,
                                    set_default_profile, DEFAULT_UMASK,
                                    create_config_noninteractive)

    only_user_config = only_config

    # Create the directories to store the configuration files
    create_base_dirs()
    if settings.AIIDADB_PROFILE and profile:
        sys.exit(
            'the profile argument cannot be used if verdi is called with -p option: {} and {}'
            .format(settings.AIIDADB_PROFILE, profile))
    gprofile = settings.AIIDADB_PROFILE or profile
    if gprofile == profile:
        settings.AIIDADB_PROFILE = profile
    if not settings.AIIDADB_PROFILE:
        settings.AIIDADB_PROFILE = 'default'

    # used internally later
    gprofile = settings.AIIDADB_PROFILE

    created_conf = None
    # ask and store the configuration of the DB
    if non_interactive:
        try:
            created_conf = create_config_noninteractive(
                profile=gprofile,
                backend=kwargs['backend'],
                email=kwargs['email'],
                db_host=kwargs['db_host'],
                db_port=kwargs['db_port'],
                db_name=kwargs['db_name'],
                db_user=kwargs['db_user'],
                db_pass=kwargs.get('db_pass', ''),
                repo=kwargs['repo'],
                force_overwrite=kwargs.get('force_overwrite', False))
        except ValueError as exception:
            click.echo("Error during configuation: {}".format(
                exception.message),
                       err=True)
            sys.exit(1)
        except KeyError as exception:
            import traceback
            click.echo(traceback.format_exc())
            click.echo(
                "--non-interactive requires all values to be given on the commandline! Missing argument: {}"
                .format(exception.message),
                err=True)
            sys.exit(1)
    else:
        try:
            created_conf = create_configuration(profile=gprofile)
        except ValueError as exception:
            print >> sys.stderr, "Error during configuration: {}".format(
                exception.message)
            sys.exit(1)

        # Set default DB profile
        set_default_profile(gprofile, force_rewrite=False)

    if only_user_config:
        print("Only user configuration requested, "
              "skipping the migrate command")
    else:
        print("Executing now a migrate command...")

        backend_choice = created_conf['AIIDADB_BACKEND']
        if backend_choice == BACKEND_DJANGO:
            print("...for Django backend")
            # The correct profile is selected within load_dbenv.
            # Setting os.umask here since sqlite database gets created in
            # this step.
            old_umask = os.umask(DEFAULT_UMASK)

            # This check should be done more properly
            # try:
            #     backend_type = get_backend_type()
            # except KeyError:
            #     backend_type = None
            #
            # if backend_type is not None and backend_type != BACKEND_DJANGO:
            #     raise InvalidOperation("An already existing database found"
            #                            "and a different than the selected"
            #                            "backend was used for its "
            #                            "management.")

            try:
                from aiida.backends.djsite.utils import pass_to_django_manage
                pass_to_django_manage([EXECNAME, 'migrate'], profile=gprofile)
            finally:
                os.umask(old_umask)

            set_backend_type(BACKEND_DJANGO)

        elif backend_choice == BACKEND_SQLA:
            print("...for SQLAlchemy backend")
            from aiida import is_dbenv_loaded
            from aiida.backends.sqlalchemy.utils import _load_dbenv_noschemacheck, check_schema_version
            from aiida.backends.profile import load_profile

            # We avoid calling load_dbenv since we want to force the schema
            # migration
            if not is_dbenv_loaded():
                settings.LOAD_DBENV_CALLED = True
                # This is going to set global variables in settings, including settings.BACKEND
                load_profile()
                _load_dbenv_noschemacheck()

            # Perform the needed migration quietly
            check_schema_version(force_migration=True)
            set_backend_type(BACKEND_SQLA)

        else:
            raise InvalidOperation("Not supported backend selected.")

    print("Database was created successfully")

    # I create here the default user
    print("Loading new environment...")
    if only_user_config:
        from aiida.backends.utils import load_dbenv, is_dbenv_loaded
        # db environment has not been loaded in this case
        if not is_dbenv_loaded():
            load_dbenv()

    from aiida.common.setup import DEFAULT_AIIDA_USER
    from aiida.orm.backend import construct_backend

    backend = construct_backend()
    if not backend.users.find(email=DEFAULT_AIIDA_USER):
        print("Installing default AiiDA user...")
        nuser = backend.users.create(email=DEFAULT_AIIDA_USER,
                                     first_name="AiiDA",
                                     last_name="Daemon")
        nuser.is_active = True
        nuser.store()

    from aiida.common.utils import get_configured_user_email
    email = get_configured_user_email()
    print("Starting user configuration for {}...".format(email))
    if email == DEFAULT_AIIDA_USER:
        print("You set up AiiDA using the default Daemon email ({}),".format(
            email))
        print("therefore no further user configuration will be asked.")
    else:
        if non_interactive:
            # Here we map the keyword arguments onto the command line arguments
            # for verdi user configure.  We have to be careful that there the
            # argument names are the same as those int he kwargs dict
            commands = [kwargs['email'], '--non-interactive']

            for arg in ('first_name', 'last_name', 'institution'):
                value = kwargs.get(arg, None)
                if value is not None:
                    commands.extend(
                        ('--{}'.format(arg.replace('_', '-')), str(value)))
        else:
            commands = [email]

        # Ask to configure the user
        try:
            # pylint: disable=no-value-for-parameter
            cmd_user.configure(commands)
        except SystemExit:
            # Have to catch this as the configure command will do a sys.exit()
            pass

    if set_default:
        set_default_profile(profile, force_rewrite=True)

    print("Setup finished.")
Ejemplo n.º 6
0
    if first_cmdline_option is not None:
        cmdprefix = "--aiida-profile="
        if first_cmdline_option.startswith(cmdprefix):
            profile_name = first_cmdline_option[len(cmdprefix):]
            # I remove the argument I just read
            actual_argv = [actual_argv[0]] + actual_argv[2:]

    if actual_argv[1] == 'migrate':
        # Perform the same loading procedure as the normal load_dbenv does
        from aiida.backends import settings
        settings.LOAD_DBENV_CALLED = True
        # We load the needed profile.
        # This is going to set global variables in settings, including
        # settings.BACKEND
        from aiida.backends.profile import load_profile
        load_profile(process=process_name, profile=profile_name)
        from aiida.backends.profile import BACKEND_DJANGO
        if settings.BACKEND != BACKEND_DJANGO:
            from aiida.common.exceptions import InvalidOperation
            raise InvalidOperation("A Django migration procedure is initiated "
                                   "but a different backend is used!")
        # We load the Django specific _load_dbenv_noschemacheck
        # When there will be a need for SQLAlchemy for a schema migration,
        # we may abstract thw _load_dbenv_noschemacheck and make a common
        # one for both backends
        from aiida.backends.djsite.utils import _load_dbenv_noschemacheck
        _load_dbenv_noschemacheck(process=process_name, profile=profile_name)
    else:
        # Load the general load_dbenv.
        from aiida.backends.utils import load_dbenv
        load_dbenv(process=process_name, profile=profile_name)
Ejemplo n.º 7
0
    parser_rev = subparsers.add_parser('revision',
                                       help='Create a new migration file')
    parser_rev.add_argument('arguments', nargs=1, help='Migration message')

    args = parser.parse_args(sys.argv[1:])

    if args.command in AVAIL_AL_COMMANDS:
        # Use the default profile if not specified
        profile_name = args.aiida_profile

        # Perform the same loading procedure as the normal load_dbenv does
        from aiida.backends import settings
        settings.LOAD_DBENV_CALLED = True
        # We load the needed profile.
        # This is going to set global variables in settings, including
        # settings.BACKEND
        load_profile(profile=profile_name)
        if settings.BACKEND != BACKEND_SQLA:
            raise InvalidOperation("A SQLAlchemy (alembic) revision "
                                   "generation procedure is initiated "
                                   "but a different backend is used!")
        _load_dbenv_noschemacheck(profile=profile_name)

        if 'arguments' in args:
            alembic_command(args.command, args.arguments)
        else:
            alembic_command(args.command)
    else:
        print("No valid command specified. The available commands are: " +
              str(AVAIL_AL_COMMANDS))