示例#1
0
    def setUpClass(cls):
        from aiida.orm.user import User
        from aiida.orm.computer import Computer
        from aiida.common.utils import get_configured_user_email
        # I create the user only once:

        # We create the user only once:
        # Otherwise, get_automatic_user() will fail when the
        # user is recreated because it caches the user!
        # In any case, store it in cls.user though
        # Other possibility: flush the user cache on delete
        users = User.search_for_users(email=get_configured_user_email())
        assert (len(users) <= 1)
        if users:
            cls.user = users[0]
        else:
            cls.user = User(get_configured_user_email())
            cls.user.password = '******'
            cls.user.save()

        try:
            cls.computer = Computer.get('test_comp')
        except NotExistent:
            cls.computer = Computer(name='test_comp',
                                    hostname='localhost',
                                    transport_type='local',
                                    scheduler_type='pbspro',
                                    workdir='/tmp/aiida')
            cls.computer.store()
示例#2
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)
示例#3
0
    def test_session_update_and_expiration_2(self):
        """
        expire_on_commit=True & committing computer and code objects with
        their built-in store function.
        """
        from aiida.backends.sqlalchemy.models.user import DbUser
        from aiida.orm.computer import Computer
        from aiida.orm.code import Code
        from aiida.orm.user import User

        session = aiida.backends.sqlalchemy.get_scoped_session()

        self.set_connection(expire_on_commit=True)

        user = User(email=get_configured_user_email())
        session.add(user._dbuser)
        session.commit()

        defaults = dict(name='localhost',
                        hostname='localhost',
                        transport_type='local',
                        scheduler_type='pbspro',
                        workdir='/tmp/aiida')
        computer = Computer(**defaults)
        computer.store()

        code = Code()
        code.set_remote_computer_exec((computer, '/x.x'))
        code.store()

        self.drop_connection()
示例#4
0
    def test_session_update_and_expiration_3(self):
        """
        expire_on_commit=False & adding manually and committing
        computer and code objects.
        """
        from aiida.orm.computer import Computer
        from aiida.orm.code import Code
        from aiida.orm.user import User

        self.set_connection(expire_on_commit=False)

        session = aiida.backends.sqlalchemy.get_scoped_session()

        user = User(email=get_configured_user_email())
        session.add(user._dbuser)
        session.commit()

        defaults = dict(name='localhost',
                        hostname='localhost',
                        transport_type='local',
                        scheduler_type='pbspro',
                        workdir='/tmp/aiida')
        computer = Computer(**defaults)
        session.add(computer._dbcomputer)
        session.commit()

        code = Code()
        code.set_remote_computer_exec((computer, '/x.x'))
        session.add(code.dbnode)
        session.commit()

        self.drop_connection()
示例#5
0
    def setUpClass(cls, *args, **kwargs):
        """
        Create some data needed for the tests
        """
        super(TestVerdiDataCommands, cls).setUpClass()

        from aiida.orm.user import User
        from aiida.orm.group import Group

        # Create a secondary user
        new_email = "[email protected]"
        new_user = User(email=new_email)
        new_user.force_save()

        # Create a group to add specific data inside
        g1 = Group(name=cls.group_name)
        g1.store()
        cls.group_id = g1.id

        cls.create_bands_data(cls.cmd_to_nodeid_map,
                              cls.cmd_to_nodeid_map_for_groups,
                              cls.cmd_to_nodeid_map_for_nuser, g1, new_user)

        cls.create_structure_data(cls.cmd_to_nodeid_map,
                                  cls.cmd_to_nodeid_map_for_groups,
                                  cls.cmd_to_nodeid_map_for_nuser, g1,
                                  new_user)

        cls.create_cif_data(cls.cmd_to_nodeid_map,
                            cls.cmd_to_nodeid_map_for_groups,
                            cls.cmd_to_nodeid_map_for_nuser, g1, new_user)

        cls.create_trajectory_data(cls.cmd_to_nodeid_map,
                                   cls.cmd_to_nodeid_map_for_groups,
                                   cls.cmd_to_nodeid_map_for_nuser, g1,
                                   new_user)
示例#6
0
    def computer_enable(self, *args):
        """
        Enable a computer.
        """
        if not is_dbenv_loaded():
            load_dbenv()

        import argparse

        from django.core.exceptions import ObjectDoesNotExist
        from aiida.common.exceptions import NotExistent
        from aiida.orm.implementation import User

        parser = argparse.ArgumentParser(prog=self.get_full_command_name(),
                                         description='Enable a computer')
        # The default states are those that are shown if no option is given
        parser.add_argument(
            '-u',
            '--only-for-user',
            type=str,
            metavar='EMAIL',
            dest='user_email',
            help="Enable a computer only for the given user. "
            "If not specified, enables the computer "
            "globally.",
        )
        parser.add_argument('computer',
                            type=str,
                            help="The name of the computer that you "
                            "want to enable")

        parsed_args = parser.parse_args(args)

        user_email = parsed_args.user_email
        computername = parsed_args.computer

        try:
            computer = self.get_computer(name=computername)
        except NotExistent:
            print >> sys.stderr, "No computer exists with name '{}'".format(
                computername)
            sys.exit(1)

        if user_email is None:
            if computer.is_enabled():
                print "Computer '{}' already enabled.".format(computername)
            else:
                computer.set_enabled_state(True)
                print "Computer '{}' enabled.".format(computername)
        else:
            user_list = User.search_for_users(email=user_email)
            if user_list is None or len(user_list) == 0:
                print >> sys.stderr, ("No user with email '{}' in the "
                                      "database.".format(user_email))
                sys.exit(1)
            user = user_list[0]
            try:
                dbauthinfo = computer.get_dbauthinfo(user._dbuser)
                if not dbauthinfo.enabled:
                    dbauthinfo.enabled = True
                    dbauthinfo.save()
                    print "Computer '{}' enabled for user {}.".format(
                        computername, user.get_full_name())
                else:
                    print "Computer '{}' was already enabled for user {} {}.".format(
                        computername, user.first_name, user.last_name)
            except NotExistent:
                print >> sys.stderr, ("User with email '{}' is not configured "
                                      "for computer '{}' yet.".format(
                                          user_email, computername))
                sys.exit(1)
示例#7
0
    def run(self, *args):
        from aiida.common.setup import (create_base_dirs, create_configuration,
                                        set_default_profile, DEFAULT_UMASK)
        from aiida.backends.profile import BACKEND_SQLA, BACKEND_DJANGO
        from aiida.backends.utils import set_backend_type, get_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

        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 = 'default' if settings_profile.AIIDADB_PROFILE is None \
            else settings_profile.AIIDADB_PROFILE

        created_conf = None
        # ask and store the configuration of the DB
        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.backends.sqlalchemy.models.base import Base
                from aiida.backends.sqlalchemy.utils import (get_engine,
                                                             install_tc)
                from aiida.common.setup import get_profile_config
                from aiida import is_dbenv_loaded, load_dbenv

                if not is_dbenv_loaded():
                    load_dbenv()

                # 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_SQLA:
                #     raise InvalidOperation("An already existing database found"
                #                            "and a different than the selected"
                #                            "backend was used for its "
                #                            "management.")

                # Those import are necessary for SQLAlchemy to correctly create
                # the needed database tables.
                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, table_groups_nodes)
                from aiida.backends.sqlalchemy.models.lock import DbLock
                from aiida.backends.sqlalchemy.models.log import DbLog
                from aiida.backends.sqlalchemy.models.node import (DbLink,
                                                                   DbNode,
                                                                   DbPath,
                                                                   DbCalcState)
                from aiida.backends.sqlalchemy.models.user import DbUser
                from aiida.backends.sqlalchemy.models.workflow import (
                    DbWorkflow, DbWorkflowData, DbWorkflowStep)
                from aiida.backends.sqlalchemy.models.settings import DbSetting

                connection = get_engine(get_profile_config(gprofile))
                Base.metadata.create_all(connection)
                install_tc(connection)

                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
            User().user_configure(email)

        print "Install finished."
示例#8
0
    def computer_disable(self, *args):
        """
        Disable a computer.

        If a computer is disabled, AiiDA does not try to connect to it to
        submit new calculations or check for the state of existing calculations.
        Useful, for instance, if you know that a computer is under maintenance.
        """
        if not is_dbenv_loaded():
            load_dbenv()

        import argparse

        from aiida.common.exceptions import NotExistent

        parser = argparse.ArgumentParser(prog=self.get_full_command_name(),
                                         description='Disable a computer')
        # The default states are those that are shown if no option is given
        parser.add_argument(
            '-u',
            '--only-for-user',
            type=str,
            metavar='EMAIL',
            dest='user_email',
            help="Disable a computer only for the given user. "
            "If not specified, disables the computer "
            "globally.",
        )
        parser.add_argument('computer',
                            type=str,
                            help="The name of the computer that you "
                            "want to disable")

        parsed_args = parser.parse_args(args)

        user_email = parsed_args.user_email
        computername = parsed_args.computer

        try:
            computer = self.get_computer(name=computername)
        except NotExistent:
            print >> sys.stderr, "No computer exists with name '{}'".format(
                computername)
            sys.exit(1)

        if user_email is None:
            if not computer.is_enabled():
                print "Computer '{}' already disabled.".format(computername)
            else:
                computer.set_enabled_state(False)
                print "Computer '{}' disabled.".format(computername)
        else:
            user_list = User.search_for_users(email=user_email)
            if user_list is None or len(user_list) == 0:
                print >> sys.stderr, ("No user with email '{}' in the "
                                      "database.".format(user_email))
                sys.exit(1)
            user = user_list[0]
            try:
                dbauthinfo = computer.get_dbauthinfo(user)
                if dbauthinfo.enabled:
                    dbauthinfo.enabled = False
                    dbauthinfo.save()
                    print "Computer '{}' disabled for user {}.".format(
                        computername, user.get_full_name())
                else:
                    print("Computer '{}' was already disabled for user {} {}.".
                          format(computername, user.first_name,
                                 user.last_name))
            except NotExistent:
                print >> sys.stderr, ("User with email '{}' is not configured "
                                      "for computer '{}' yet.".format(
                                          user_email, computername))
示例#9
0
    def computer_test(self, *args):
        """
        Test the connection to a computer.

        It tries to connect, to get the list of calculations on the queue and
        to perform other tests.
        """
        import argparse
        import traceback

        if not is_dbenv_loaded():
            load_dbenv()

        from django.core.exceptions import ObjectDoesNotExist
        from aiida.common.exceptions import NotExistent
        from aiida.orm.user import User
        from aiida.backends.utils import get_automatic_user
        from aiida.orm.computer import Computer as OrmComputer

        parser = argparse.ArgumentParser(prog=self.get_full_command_name(),
                                         description='Test a remote computer')
        # The default states are those that are shown if no option is given
        parser.add_argument(
            '-u',
            '--user',
            type=str,
            metavar='EMAIL',
            dest='user_email',
            help="Test the connection for a given AiiDA user."
            "If not specified, uses the current "
            "default user.",
        )
        parser.add_argument(
            '-t',
            '--traceback',
            action='store_true',
            help="Print the full traceback in case an exception "
            "is raised",
        )
        parser.add_argument('computer',
                            type=str,
                            help="The name of the computer that you "
                            "want to test")

        parsed_args = parser.parse_args(args)

        user_email = parsed_args.user_email
        computername = parsed_args.computer
        print_traceback = parsed_args.traceback

        try:
            computer = self.get_computer(name=computername)
        except NotExistent:
            print >> sys.stderr, "No computer exists with name '{}'".format(
                computername)
            sys.exit(1)

        if user_email is None:
            user = User(dbuser=get_automatic_user())
        else:
            user_list = User.search_for_users(email=user_email)
            # If no user is found
            if not user_list:
                print >> sys.stderr, ("No user with email '{}' in the "
                                      "database.".format(user_email))
                sys.exit(1)
            user = user_list[0]

        print "Testing computer '{}' for user {}...".format(
            computername, user.email)
        try:
            dbauthinfo = computer.get_dbauthinfo(user._dbuser)
        except NotExistent:
            print >> sys.stderr, ("User with email '{}' is not yet configured "
                                  "for computer '{}' yet.".format(
                                      user.email, computername))
            sys.exit(1)

        warning_string = None
        if not dbauthinfo.enabled:
            warning_string = (
                "** NOTE! Computer is disabled for the "
                "specified user!\n   Do you really want to test it? [y/N] ")
        if not computer.is_enabled():
            warning_string = ("** NOTE! Computer is disabled!\n"
                              "   Do you really want to test it? [y/N] ")
        if warning_string:
            answer = raw_input(warning_string)
            if not (answer == 'y' or answer == 'Y'):
                sys.exit(0)

        s = OrmComputer(dbcomputer=dbauthinfo.dbcomputer).get_scheduler()
        t = dbauthinfo.get_transport()

        ## STARTING TESTS HERE
        num_failures = 0
        num_tests = 0

        try:
            print "> Testing connection..."
            with t:
                s.set_transport(t)
                num_tests += 1
                for test in [
                        self._computer_test_get_jobs,
                        self._computer_create_temp_file
                ]:
                    num_tests += 1
                    try:
                        succeeded = test(transport=t,
                                         scheduler=s,
                                         dbauthinfo=dbauthinfo)
                    except Exception as e:
                        print "* The test raised an exception!"
                        if print_traceback:
                            print "** Full traceback:"
                            # Indent
                            print "\n".join([
                                "   {}".format(l)
                                for l in traceback.format_exc().splitlines()
                            ])
                        else:
                            print "** {}: {}".format(e.__class__.__name__,
                                                     e.message)
                            print(
                                "** (use the --traceback option to see the "
                                "full traceback)")
                        succeeded = False

                    if not succeeded:
                        num_failures += 1

            if num_failures:
                print "Some tests failed! ({} out of {} failed)".format(
                    num_failures, num_tests)
            else:
                print "Test completed (all {} tests succeeded)".format(
                    num_tests)
        except Exception as e:
            print "** Error while trying to connect to the computer! I cannot "
            print "   perform following tests, so I stop."
            if print_traceback:
                print "** Full traceback:"
                # Indent
                print "\n".join([
                    "   {}".format(l)
                    for l in traceback.format_exc().splitlines()
                ])
            else:
                print "{}: {}".format(e.__class__.__name__, e.message)
                print(
                    "(use the --traceback option to see the "
                    "full traceback)")
            succeeded = False
示例#10
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."
示例#11
0
    def get_bands_and_parents_structure(self, args):
        """
        Search for bands and return bands and the closest structure that is a parent of the instance.
        This is the backend independent way, can be overriden for performance reason

        :returns:
            A list of sublists, each latter containing (in order):
                pk as string, formula as string, creation date, bandsdata-label
        """

        import datetime
        from aiida.utils import timezone
        from aiida.orm.querybuilder import QueryBuilder
        from aiida.backends.utils import get_automatic_user
        from aiida.orm.implementation import User
        from aiida.orm.implementation import Group
        from aiida.orm.data.structure import (get_formula, get_symbols_string)
        from aiida.orm.data.array.bands import BandsData
        from aiida.orm.data.structure import StructureData

        qb = QueryBuilder()
        if args.all_users is False:
            au = get_automatic_user()
            user = User(dbuser=au)
            qb.append(User, tag="creator", filters={"email": user.email})
        else:
            qb.append(User, tag="creator")

        bdata_filters = {}
        if args.past_days is not None:
            now = timezone.now()
            n_days_ago = now - datetime.timedelta(days=args.past_days)
            bdata_filters.update({"ctime": {'>=': n_days_ago}})

        qb.append(BandsData,
                  tag="bdata",
                  created_by="creator",
                  filters=bdata_filters,
                  project=["id", "label", "ctime"])

        group_filters = {}

        if args.group_name is not None:
            group_filters.update({"name": {"in": args.group_name}})
        if args.group_pk is not None:
            group_filters.update({"id": {"in": args.group_pk}})
        if group_filters:
            qb.append(Group,
                      tag="group",
                      filters=group_filters,
                      group_of="bdata")

        qb.append(
            StructureData,
            tag="sdata",
            ancestor_of="bdata",
            # We don't care about the creator of StructureData
            project=["id", "attributes.kinds", "attributes.sites"])

        qb.order_by({StructureData: {'ctime': 'desc'}})

        list_data = qb.distinct()

        entry_list = []
        already_visited_bdata = set()

        for [bid, blabel, bdate, sid, akinds, asites] in list_data.all():

            # We process only one StructureData per BandsData.
            # We want to process the closest StructureData to
            # every BandsData.
            # We hope that the StructureData with the latest
            # creation time is the closest one.
            # This will be updated when the QueryBuilder supports
            # order_by by the distance of two nodes.
            if already_visited_bdata.__contains__(bid):
                continue
            already_visited_bdata.add(bid)

            if args.element is not None:
                all_symbols = [_["symbols"][0] for _ in akinds]
                if not any([s in args.element for s in all_symbols]):
                    continue

            if args.element_only is not None:
                all_symbols = [_["symbols"][0] for _ in akinds]
                if not all([s in all_symbols for s in args.element_only]):
                    continue

            # We want only the StructureData that have attributes
            if akinds is None or asites is None:
                continue

            symbol_dict = {}
            for k in akinds:
                symbols = k['symbols']
                weights = k['weights']
                symbol_dict[k['name']] = get_symbols_string(symbols, weights)

            try:
                symbol_list = []
                for s in asites:
                    symbol_list.append(symbol_dict[s['kind_name']])
                formula = get_formula(symbol_list, mode=args.formulamode)
            # If for some reason there is no kind with the name
            # referenced by the site
            except KeyError:
                formula = "<<UNKNOWN>>"
            entry_list.append(
                [str(bid),
                 str(formula),
                 bdate.strftime('%d %b %Y'), blabel])

        return entry_list
示例#12
0
    def code_list(self, *args):
        """
        List available codes
        """
        import argparse

        parser = argparse.ArgumentParser(
            prog=self.get_full_command_name(),
            description='List the codes in the database.')
        # The default states are those that are shown if no option is given
        parser.add_argument(
            '-c',
            '--computer',
            help="Filter only codes on a given computer",
        )
        parser.add_argument(
            '-p',
            '--plugin',
            help="Filter only calculation with a given plugin",
        )
        parser.add_argument(
            '-A',
            '--all-users',
            dest='all_users',
            action='store_true',
            help="Show codes of all users",
        )
        parser.add_argument(
            '-o',
            '--show-owner',
            dest='show_owner',
            action='store_true',
            help="Show also the owner of the code",
        )
        parser.add_argument(
            '-a',
            '--all-codes',
            action='store_true',
            help="Show also hidden codes",
        )
        parser.set_defaults(all_users=False, hidden=False)
        parsed_args = parser.parse_args(args)
        computer_filter = parsed_args.computer
        plugin_filter = parsed_args.plugin
        all_users = parsed_args.all_users
        show_owner = parsed_args.show_owner
        reveal_filter = parsed_args.all_codes

        from aiida.orm.querybuilder import QueryBuilder
        from aiida.orm.code import Code
        from aiida.orm.computer import Computer
        from aiida.orm.user import User
        from aiida.backends.utils import get_automatic_user

        qb_user_filters = dict()
        if not all_users:
            user = User(dbuser=get_automatic_user())
            qb_user_filters['email'] = user.email

        qb_computer_filters = dict()
        if computer_filter is not None:
            qb_computer_filters['name'] = computer_filter

        qb_code_filters = dict()
        if plugin_filter is not None:
            qb_code_filters['attributes.input_plugin'] = plugin_filter

        if not reveal_filter:
            qb_code_filters['attributes.hidden'] = {"~==": True}

        qb = QueryBuilder()
        qb.append(Code,
                  tag="code",
                  filters=qb_code_filters,
                  project=["id", "label"])
        qb.append(Computer,
                  computer_of="code",
                  project=["name"],
                  filters=qb_computer_filters)
        qb.append(User,
                  creator_of="code",
                  project=["email"],
                  filters=qb_user_filters)

        print "# List of configured codes:"
        print "# (use 'verdi code show CODEID' to see the details)"
        if qb.count > 0:
            for pk, label, computername, useremail in qb.iterall():
                if show_owner:
                    owner_string = " ({})".format(useremail)
                else:
                    owner_string = ""
                if computername is None:
                    computernamestring = ""
                else:
                    computernamestring = "@{}".format(computername)
                print "* pk {} - {}{}{}".format(pk, label, computernamestring,
                                                owner_string)
        else:
            print "# No codes found matching the specified criteria."
示例#13
0
    def code_list(self, *args):
        """
        List available codes
        """
        import argparse

        parser = argparse.ArgumentParser(
            prog=self.get_full_command_name(),
            description='List the codes in the database.')
        # The default states are those that are shown if no option is given
        parser.add_argument(
            '-c',
            '--computer',
            help="Filter only codes on a given computer",
        )
        parser.add_argument(
            '-p',
            '--plugin',
            help="Filter only calculation with a given plugin",
        )
        parser.add_argument(
            '-A',
            '--all-users',
            dest='all_users',
            action='store_true',
            help="Show codes of all users",
        )
        parser.add_argument(
            '-o',
            '--show-owner',
            dest='show_owner',
            action='store_true',
            help="Show also the owner of the code",
        )
        parser.add_argument(
            '-a',
            '--all-codes',
            action='store_true',
            help="Show also hidden codes",
        )
        parser.set_defaults(all_users=False, hidden=False)
        parsed_args = parser.parse_args(args)
        computer_filter = parsed_args.computer
        plugin_filter = parsed_args.plugin
        all_users = parsed_args.all_users
        show_owner = parsed_args.show_owner
        reveal_filter = parsed_args.all_codes

        from aiida.orm.querybuilder import QueryBuilder
        from aiida.orm.code import Code
        from aiida.orm.computer import Computer
        from aiida.orm.user import User
        from aiida.backends.utils import get_automatic_user

        qb_user_filters = dict()
        if not all_users:
            user = User(dbuser=get_automatic_user())
            qb_user_filters['email'] = user.email

        qb_computer_filters = dict()
        if computer_filter is not None:
            qb_computer_filters['name'] = computer_filter

        qb_code_filters = dict()
        if plugin_filter is not None:
            qb_code_filters['attributes.input_plugin'] = plugin_filter

        if not reveal_filter:
            qb_code_filters['attributes.hidden'] = {"~==": True}

        print "# List of configured codes:"
        print "# (use 'verdi code show CODEID' to see the details)"
        if computer_filter is not None:
            qb = QueryBuilder()
            qb.append(Code,
                      tag="code",
                      filters=qb_code_filters,
                      project=["id", "label"])
            # We have a user assigned to the code so we can ask for the
            # presence of a user even if there is no user filter
            qb.append(User,
                      creator_of="code",
                      project=["email"],
                      filters=qb_user_filters)
            # We also add the filter on computer. This will automatically
            # return codes that have a computer (and of course satisfy the
            # other filters). The codes that have a computer attached are the
            # remote codes.
            qb.append(Computer,
                      computer_of="code",
                      project=["name"],
                      filters=qb_computer_filters)
            self.print_list_res(qb, show_owner)

        # If there is no filter on computers
        else:
            # Print all codes that have a computer assigned to them
            # (these are the remote codes)
            qb = QueryBuilder()
            qb.append(Code,
                      tag="code",
                      filters=qb_code_filters,
                      project=["id", "label"])
            # We have a user assigned to the code so we can ask for the
            # presence of a user even if there is no user filter
            qb.append(User,
                      creator_of="code",
                      project=["email"],
                      filters=qb_user_filters)
            qb.append(Computer, computer_of="code", project=["name"])
            self.print_list_res(qb, show_owner)

            # Now print all the local codes. To get the local codes we ask
            # the dbcomputer_id variable to be None.
            qb = QueryBuilder()
            comp_non_existence = {"dbcomputer_id": {"==": None}}
            if not qb_code_filters:
                qb_code_filters = comp_non_existence
            else:
                new_qb_code_filters = {
                    "and": [qb_code_filters, comp_non_existence]
                }
                qb_code_filters = new_qb_code_filters
            qb.append(Code,
                      tag="code",
                      filters=qb_code_filters,
                      project=["id", "label"])
            # We have a user assigned to the code so we can ask for the
            # presence of a user even if there is no user filter
            qb.append(User,
                      creator_of="code",
                      project=["email"],
                      filters=qb_user_filters)
            self.print_list_res(qb, show_owner)
示例#14
0
def test_configure_from_file(configure):
    from aiida.orm.user import User
    user = User.get_all_users()[0]
    assert user.first_name == 'AiiDA'
示例#15
0
    def test_6(self):
        """
        This test checks that nodes belonging to user A (which is not the
        default user) can be correctly exported, imported, enriched with nodes
        from the default user, re-exported & re-imported and that in the end
        all the nodes that have been finally imported belonging to the right
        users.
        """
        import os
        import shutil
        import tempfile

        from aiida.orm import load_node
        from aiida.orm.calculation.job import JobCalculation
        from aiida.orm.data.structure import StructureData
        from aiida.orm.importexport import export
        from aiida.common.datastructures import calc_states
        from aiida.common.links import LinkType
        from aiida.common.utils import get_configured_user_email
        from aiida.orm.user import User

        # Creating a folder for the import/export files
        temp_folder = tempfile.mkdtemp()
        try:
            # Create another user
            new_email = "[email protected]"
            user = User(email=new_email)
            user.force_save()

            # Create a structure data node that has a calculation as output
            sd1 = StructureData()
            sd1.dbnode.user = user._dbuser
            sd1.label = 'sd1'
            sd1.store()

            jc1 = JobCalculation()
            jc1.set_computer(self.computer)
            jc1.set_resources({"num_machines": 1, "num_mpiprocs_per_machine": 1})
            jc1.dbnode.user = user._dbuser
            jc1.label = 'jc1'
            jc1.store()
            jc1.add_link_from(sd1)
            jc1._set_state(calc_states.PARSING)

            # Create some nodes from a different user
            sd2 = StructureData()
            sd2.dbnode.user = user._dbuser
            sd2.label = 'sd2'
            sd2.store()
            sd2.add_link_from(jc1, label='l1', link_type=LinkType.RETURN)

            # Set the jc1 to FINISHED
            jc1._set_state(calc_states.FINISHED)

            # At this point we export the generated data
            filename1 = os.path.join(temp_folder, "export1.tar.gz")
            export([sd2.dbnode], outfile=filename1, silent=True)
            uuids1 = [sd1.uuid, jc1.uuid, sd2.uuid]
            self.clean_db()
            self.insert_data()
            import_data(filename1, silent=True)

            # Check that the imported nodes are correctly imported and that
            # the user assigned to the nodes is the right one
            for uuid in uuids1:
                self.assertEquals(load_node(uuid).get_user().email, new_email)

            # Now we continue to generate more data based on the imported
            # data
            sd2_imp = load_node(sd2.uuid)

            jc2 = JobCalculation()
            jc2.set_computer(self.computer)
            jc2.set_resources({"num_machines": 1, "num_mpiprocs_per_machine": 1})
            jc2.label = 'jc2'
            jc2.store()
            jc2.add_link_from(sd2_imp, label='l2')
            jc2._set_state(calc_states.PARSING)

            sd3 = StructureData()
            sd3.label = 'sd3'
            sd3.store()
            sd3.add_link_from(jc2, label='l3', link_type=LinkType.RETURN)

            # Set the jc2 to FINISHED
            jc2._set_state(calc_states.FINISHED)

            # Store the UUIDs of the nodes that should be checked
            # if they can be imported correctly.
            uuids2 = [jc2.uuid, sd3.uuid]

            filename2 = os.path.join(temp_folder, "export2.tar.gz")
            export([sd3.dbnode], outfile=filename2, silent=True)
            self.clean_db()
            self.insert_data()
            import_data(filename2, silent=True)

            # Check that the imported nodes are correctly imported and that
            # the user assigned to the nodes is the right one
            for uuid in uuids1:
                self.assertEquals(load_node(uuid).get_user().email, new_email)
            for uuid in uuids2:
                self.assertEquals(load_node(uuid).get_user().email,
                                  get_configured_user_email())

        finally:
            # Deleting the created temporary folder
            shutil.rmtree(temp_folder, ignore_errors=True)
示例#16
0
    def test_5(self):
        """
        This test checks that nodes belonging to different users are correctly
        exported & imported.
        """
        import os
        import shutil
        import tempfile

        from aiida.orm import load_node
        from aiida.orm.calculation.job import JobCalculation
        from aiida.orm.data.structure import StructureData
        from aiida.orm.importexport import export
        from aiida.common.datastructures import calc_states
        from aiida.common.links import LinkType
        from aiida.orm.user import User
        from aiida.common.utils import get_configured_user_email

        # Creating a folder for the import/export files
        temp_folder = tempfile.mkdtemp()
        try:
            # Create another user
            new_email = "[email protected]"
            user = User(email=new_email)
            user.force_save()

            # Create a structure data node that has a calculation as output
            sd1 = StructureData()
            sd1.dbnode.user = user._dbuser
            sd1.label = 'sd1'
            sd1.store()

            jc1 = JobCalculation()
            jc1.set_computer(self.computer)
            jc1.set_resources({"num_machines": 1, "num_mpiprocs_per_machine": 1})
            jc1.dbnode.user = user._dbuser
            jc1.label = 'jc1'
            jc1.store()
            jc1.add_link_from(sd1)
            jc1._set_state(calc_states.PARSING)

            # Create some nodes from a different user
            sd2 = StructureData()
            sd2.dbnode.user = user._dbuser
            sd2.label = 'sd2'
            sd2.store()
            sd2.add_link_from(jc1, label='l1', link_type=LinkType.RETURN)

            jc2 = JobCalculation()
            jc2.set_computer(self.computer)
            jc2.set_resources({"num_machines": 1, "num_mpiprocs_per_machine": 1})
            jc2.label = 'jc2'
            jc2.store()
            jc2.add_link_from(sd2, label='l2')
            jc2._set_state(calc_states.PARSING)

            sd3 = StructureData()
            sd3.label = 'sd3'
            sd3.store()
            sd3.add_link_from(jc2, label='l3', link_type=LinkType.RETURN)

            uuids_u1 = [sd1.uuid, jc1.uuid, sd2.uuid]
            uuids_u2 = [jc2.uuid, sd3.uuid]

            filename = os.path.join(temp_folder, "export.tar.gz")

            export([sd3.dbnode], outfile=filename, silent=True)
            self.clean_db()
            import_data(filename, silent=True)

            # Check that the imported nodes are correctly imported and that
            # the user assigned to the nodes is the right one
            for uuid in uuids_u1:
                self.assertEquals(load_node(uuid).get_user().email, new_email)
            for uuid in uuids_u2:
                self.assertEquals(load_node(uuid).get_user().email,
                                  get_configured_user_email())
        finally:
            # Deleting the created temporary folder
            shutil.rmtree(temp_folder, ignore_errors=True)
示例#17
0
    def configure_user(self, *args):
        """
        Configure the user that can run the daemon.
        """
        if not is_dbenv_loaded():
            from aiida.backends.utils import load_dbenv
            load_dbenv(process='daemon')

        if args:
            print >> sys.stderr, (
                "No arguments allowed for the '{}' command.".format(
                    self.get_full_command_name()))
            sys.exit(1)

        from aiida.utils import timezone
        from aiida.backends.utils import get_daemon_user, set_daemon_user
        from aiida.common.utils import (get_configured_user_email,
                                        query_yes_no, query_string)
        from aiida.daemon.timestamps import get_most_recent_daemon_timestamp
        from aiida.common.utils import str_timedelta
        from aiida.orm.user import User

        old_daemon_user = get_daemon_user()
        this_user = get_configured_user_email()

        print("> Current default user: {}".format(this_user))
        print("> Currently configured user who can run the daemon: {}".format(
            old_daemon_user))
        if old_daemon_user == this_user:
            print(
                "  (therefore, at the moment you are the user who can run "
                "the daemon)")
            pid = self.get_daemon_pid()
            if pid is not None:
                print("The daemon is running! I will not proceed.")
                sys.exit(1)
        else:
            print("  (therefore, you cannot run the daemon, at the moment)")

        most_recent_timestamp = get_most_recent_daemon_timestamp()

        print "*" * 76
        print "* {:72s} *".format("WARNING! Change this setting only if you "
                                  "are sure of what you are doing.")
        print "* {:72s} *".format("Moreover, make sure that the "
                                  "daemon is stopped.")

        if most_recent_timestamp is not None:
            timestamp_delta = timezone.now() - most_recent_timestamp
            last_check_string = (
                "[The most recent timestamp from the daemon was {}]".format(
                    str_timedelta(timestamp_delta)))
            print "* {:72s} *".format(last_check_string)

        print "*" * 76

        answer = query_yes_no(
            "Are you really sure that you want to change "
            "the daemon user?",
            default="no")
        if not answer:
            sys.exit(0)

        print ""
        print "Enter below the email of the new user who can run the daemon."
        new_daemon_user_email = query_string("New daemon user: "******"ERROR! The user you specified ({}) does "
                "not exist in the database!!".format(new_daemon_user_email))
            print("The available users are {}".format(
                [_.email for _ in User.search_for_users()]))
            sys.exit(1)

        set_daemon_user(new_daemon_user_email)

        print "The new user that can run the daemon is now {} {}.".format(
            found_users[0].first_name, found_users[0].last_name)
示例#18
0
 def get_aiida_class(self):
     from aiida.orm.user import User
     return User(dbuser=self)