Esempio n. 1
0
def workflow_list(short, all_states, depth, past_days, workflows):
    """List legacy workflows"""
    from aiida.backends.utils import get_workflow_list
    from aiida.orm.workflow import get_workflow_info
    from aiida.orm.backend import construct_backend  # pylint: disable=no-name-in-module
    tab_size = 2

    backend = construct_backend()
    current_user = backend.users.get_automatic_user()

    wf_list = get_workflow_list([workflow.pk for workflow in workflows],
                                user=current_user,
                                all_states=all_states,
                                n_days_ago=past_days)
    for workflow in wf_list:
        if not workflow.is_subworkflow() or workflow in workflows:
            echo.echo('\n'.join(
                get_workflow_info(workflow,
                                  tab_size=tab_size,
                                  short=short,
                                  depth=depth)))

    if not workflows:
        if all_states:
            echo.echo_info('# No workflows found')
        else:
            echo.echo_info('# No running workflows found')
Esempio n. 2
0
def update(comment, node, comment_id):
    """
    Update a comment.

    id      = The id of the comment
    comment = The comment (a string) to be added to the node(s)
    """
    from aiida.orm.backend import construct_backend
    backend = construct_backend()
    user = backend.users.get_automatic_user()

    # read the comment from terminal if it is not on command line
    if comment is None:
        try:
            current_comment = node.get_comments(comment_id)[0]
        except IndexError:
            echo.echo_error(
                "Comment with id '{}' not found".format(comment_id))
            return 1

        comment = multi_line_input.edit_comment(current_comment['content'])

    # pylint: disable=protected-access
    node._update_comment(comment, comment_id, user)

    return 0
Esempio n. 3
0
    def get_transport(self, user=None):
        """
        Return a Tranport class, configured with all correct parameters.
        The Transport is closed (meaning that if you want to run any operation with
        it, you have to open it first (i.e., e.g. for a SSH tranport, you have
        to open a connection). To do this you can call ``transport.open()``, or simply
        run within a ``with`` statement::

           transport = Computer.get_transport()
           with transport:
               print(transport.whoami())

        :param user: if None, try to obtain a transport for the default user.
            Otherwise, pass a valid User.

        :return: a (closed) Transport, already configured with the connection
            parameters to the supercomputer, as configured with ``verdi computer configure``
            for the user specified as a parameter ``user``.
        """
        from aiida.orm.backend import construct_backend
        backend = construct_backend()
        if user is None:
            authinfo = backend.authinfos.get(self, backend.users.get_automatic_user())
        else:
            authinfo = backend.authinfos.get(self, user)
        transport = authinfo.get_transport()

        return transport
Esempio n. 4
0
def create_authinfo(computer, store=False):
    """
    Allow the current user to use the given computer.

    Deal with backwards compatibility down to aiida 0.11
    """
    from aiida.orm import backend as orm_backend
    authinfo = None
    if hasattr(orm_backend, 'construct_backend'):
        backend = orm_backend.construct_backend()
        authinfo = backend.authinfos.create(computer=computer, user=get_current_user())
        if store:
            authinfo.store()
    else:
        from aiida.backends.settings import BACKEND
        from aiida.backends.profile import BACKEND_SQLA, BACKEND_DJANGO

        if BACKEND == BACKEND_DJANGO:
            from aiida.backends.djsite.db.models import DbAuthInfo
            authinfo = DbAuthInfo(dbcomputer=computer.dbcomputer, aiidauser=get_current_user())
        elif BACKEND == BACKEND_SQLA:
            from aiida.backends.sqlalchemy.models.authinfo import DbAuthInfo
            from aiida.backends.sqlalchemy import get_scoped_session
            _ = get_scoped_session()
            authinfo = DbAuthInfo(dbcomputer=computer.dbcomputer, aiidauser=get_current_user())
        if store:
            authinfo.save()
    return authinfo
Esempio n. 5
0
    def test_workflow_info(self):
        """
        This test checks that the workflow info is generate without any
        exceptions
        :return:
        """
        backend = construct_backend()

        # Assuming there is only one user
        user = backend.users.find(email=self.user_email)[0]

        # Creating a simple workflow & storing it
        a = WFTestEmpty()
        a.store()

        # Emulate the workflow list
        for w in get_workflow_list(all_states=True, user=user):
            if not w.is_subworkflow():
                get_workflow_info(w)

        # Create a workflow with sub-workflows and store it
        b = WFTestSimpleWithSubWF()
        b.store()

        # Emulate the workflow list
        for w in get_workflow_list(all_states=True, user=user):
            if not w.is_subworkflow():
                get_workflow_info(w)

        # Start the first workflow and perform a workflow list
        b.start()
        for w in get_workflow_list(all_states=True, user=user):
            if not w.is_subworkflow():
                get_workflow_info(w)
Esempio n. 6
0
def configure_computer(computer, user=None, **kwargs):
    """Configure a computer for a user with valid auth params passed via kwargs."""
    from aiida.orm.backend import construct_backend

    transport_cls = computer.get_transport_class()
    backend = construct_backend()
    user = user or backend.users.get_automatic_user()

    try:
        authinfo = computer.get_authinfo(user)
    except NotExistent:
        authinfo = backend.authinfos.create(computer, user)

    auth_params = authinfo.get_auth_params()
    valid_keys = set(transport_cls.get_valid_auth_params())

    if not set(kwargs.keys()).issubset(valid_keys):
        invalid_keys = [key for key in kwargs if key not in valid_keys]
        raise ValueError('{transport}: recieved invalid authentication parameter(s) "{invalid}"'.format(
            transport=transport_cls, invalid=invalid_keys))

    if valid_keys:
        auth_params.update(kwargs)
        authinfo.set_auth_params(auth_params)
        from aiida.settings import BACKEND
        if BACKEND == 'sqlalchemy':
            authinfo._dbauthinfo.auth_params = auth_params  # pylint: disable=protected-access
    authinfo.store()
Esempio n. 7
0
def get_automatic_user():
    try:
        from aiida.backends.utils import get_automatic_user
        automatic_user = get_automatic_user()
    except ImportError:
        from aiida.orm.backend import construct_backend
        backend = construct_backend()
        automatic_user = backend.users.get_automatic_user()
    return automatic_user
Esempio n. 8
0
 def _backend(self):
     """
     Get the backend
     """
     if self.__backend is None:
         # Lazy load the backend so we don't do it too early (i.e. before load_dbenv())
         from aiida.orm.backend import construct_backend
         self.__backend = construct_backend()
     return self.__backend
Esempio n. 9
0
def kill_all():
    from aiida.orm.backend import construct_backend
    backend = construct_backend()
    automatic_user = backend.users.get_automatic_user()
    w_list = DbWorkflow.query.filter(
        DbWorkflow.user == automatic_user.dbuser,
        DbWorkflow.state != wf_states.FINISHED).all()

    for w in w_list:
        Workflow.get_subclass_from_uuid(w.uuid).kill()
Esempio n. 10
0
def calculation_cleanworkdir(calculations, past_days, older_than, computers,
                             force):
    """
    Clean all content of all output remote folders of calculations.

    If no explicit calculations are specified as arguments, one or both of the -p and -o options has to be specified.
    If both are specified, a logical AND is done between the two, i.e. the calculations that will be cleaned have been
    modified AFTER [-p option] days from now, but BEFORE [-o option] days from now.
    """
    from aiida.orm.backend import construct_backend
    from aiida.orm.utils.loaders import ComputerEntityLoader, IdentifierType
    from aiida.orm.utils.remote import clean_remote, get_calculation_remote_paths

    if calculations:
        if (past_days is not None and older_than is not None):
            echo.echo_critical(
                'specify either explicit calculations or use the filtering options'
            )
    else:
        if (past_days is None and older_than is None):
            echo.echo_critical(
                'if no explicit calculations are specified, at least one filtering option is required'
            )

    calculations_pks = [calculation.pk for calculation in calculations]
    path_mapping = get_calculation_remote_paths(calculations_pks, past_days,
                                                older_than, computers)

    if path_mapping is None:
        echo.echo_critical('no calculations found with the given criteria')

    if not force:
        path_count = sum(
            [len(paths) for computer, paths in path_mapping.items()])
        warning = 'Are you sure you want to clean the work directory of {} calculations?'.format(
            path_count)
        click.confirm(warning, abort=True)

    backend = construct_backend()
    user = backend.users.get_automatic_user()

    for computer_uuid, paths in path_mapping.items():

        counter = 0
        computer = ComputerEntityLoader.load_entity(
            computer_uuid, identifier_type=IdentifierType.UUID)
        transport = backend.authinfos.get(computer, user).get_transport()

        with transport:
            for path in paths:
                clean_remote(transport, path)
                counter += 1

        echo.echo_success('{} remote folders cleaned on {}'.format(
            counter, computer.name))
Esempio n. 11
0
def kill_all():
    from aiida.backends.djsite.db.models import DbWorkflow
    from aiida.orm.backend import construct_backend
    backend = construct_backend()

    q_object = Q(user=backend.users.get_automatic_user().id)
    q_object.add(~Q(state=wf_states.FINISHED), Q.AND)
    w_list = DbWorkflow.objects.filter(q_object)

    for w in w_list:
        Workflow.get_subclass_from_uuid(w.uuid).kill()
Esempio n. 12
0
def get_current_user():
    """Get current user backwards compatibly with aiida-core <= 0.12.1."""
    current_user = None
    if backend_obj_users():
        from aiida.orm.backend import construct_backend  # pylint: disable=no-name-in-module
        backend = construct_backend()
        current_user = backend.users.get_automatic_user()
    else:
        from aiida.backends.utils import get_automatic_user  # pylint: disable=no-name-in-module
        current_user = get_automatic_user()
    return current_user
Esempio n. 13
0
def get_computer(name=TEST_COMPUTER, workdir=None, configure=False):
    """Get local computer.

    Sets up local computer with 'name' or reads it from database,
    if it exists.

    :param name: Name of local computer
    :param workdir: path to work directory (required if creating a new computer)
    :param configure: whether to congfigure a new computer for the user email

    :return: The computer node
    :rtype: :py:class:`aiida.orm.Computer`
    """
    from aiida.common.exceptions import NotExistent

    if aiida_version() >= cmp_version("1.0.0a2"):
        from aiida.orm.backend import construct_backend
        backend = construct_backend()
        get_computer = lambda name: backend.computers.get(name=name)
        create_computer = backend.computers.create
    else:
        from aiida.orm import Computer
        get_computer = Computer.get
        create_computer = Computer

    try:
        computer = get_computer(name)
    except NotExistent:

        if workdir is None:
            raise ValueError(
                "to create a new computer, a work directory must be supplied")

        computer = create_computer(
            name=name,
            description='localhost computer set up by aiida_crystal17 tests',
            hostname=name,
            workdir=workdir,
            transport_type='local',
            scheduler_type='direct',
            enabled_state=True)
        computer.store()

        if configure:
            try:
                # aiida-core v1
                from aiida.control.computer import configure_computer
                configure_computer(computer)
            except ImportError:
                configure_computer_v012(computer)

    return computer
Esempio n. 14
0
    def get_report_messages(pk, depth, levelname):
        """Return list of log messages with given levelname and their depth for a node with a given pk."""
        backend = construct_backend()
        filters = {
            'objpk': pk,
        }

        entries = backend.logs.find(filter_by=filters)
        entries = [
            entry for entry in entries
            if LOG_LEVELS[entry.levelname] >= LOG_LEVELS[levelname]
        ]
        return [(_, depth) for _ in entries]
Esempio n. 15
0
    def setUpClass(cls, *args, **kwargs):
        from aiida.orm.backend import construct_backend

        # Note: this will raise an exception, that will be seen as a test
        # failure. To be safe, you should do the same check also in the tearDownClass
        # to avoid that it is run
        check_if_tests_can_run()

        cls.__backend_instance = cls.get_backend_class()()
        cls.__backend_instance.setUpClass_method(*args, **kwargs)
        cls.backend = construct_backend()

        cls._class_was_setup = True
Esempio n. 16
0
    def complete(self, ctx, incomplete):  # pylint: disable=unused-argument,no-self-use
        """
        Return possible completions based on an incomplete value

        :returns: list of tuples of valid entry points (matching incomplete) and a description
        """
        from aiida.orm.backend import construct_backend

        backend = construct_backend()
        users = backend.users.find()

        return [(user.email, '') for user in users
                if user.email.startswith(incomplete)]
Esempio n. 17
0
 def setUpClass(cls):
     super(TestVerdiDataRemote, cls).setUpClass()
     new_comp = Computer(name='comp',
                         hostname='localhost',
                         transport_type='local',
                         scheduler_type='direct',
                         workdir=tempfile.mkdtemp())
     new_comp.store()
     b = construct_backend()
     aiidauser = b.users.get_automatic_user()
     authinfo = DbAuthInfo(dbcomputer=new_comp.dbcomputer,
                           aiidauser=aiidauser.dbuser)
     authinfo.save()
Esempio n. 18
0
 def setUp(self):
     super(TestBackendLog, self).setUp()
     self._backend = construct_backend()
     self._record = {
         'time': now(),
         'loggername': 'loggername',
         'levelname': logging.getLevelName(LOG_LEVEL_REPORT),
         'objname': 'objname',
         'objpk': 0,
         'message': 'This is a template record message',
         'metadata': {
             'content': 'test'
         },
     }
 def setUp(self):
     """Prepare current user and computer builder with common properties."""
     from aiida.orm.backend import construct_backend
     from aiida.scheduler import SchedulerFactory
     backend = construct_backend()
     self.comp_builder = ComputerBuilder(label='test', description='Test Computer', enabled=True, hostname='localhost')
     self.comp_builder.scheduler = 'direct'
     self.comp_builder.work_dir = '/tmp/aiida'
     self.comp_builder.prepend_text = ''
     self.comp_builder.append_text = ''
     self.comp_builder.mpiprocs_per_machine = 8
     self.comp_builder.mpirun_command = 'mpirun'
     self.comp_builder.shebang = '#!xonsh'
     self.user = backend.users.get_automatic_user()
Esempio n. 20
0
def configure_computer_main(computer, user, **kwargs):
    """Configure a computer via the CLI."""
    from aiida.orm.backend import construct_backend
    from aiida.control.computer import configure_computer
    from aiida.common.utils import get_configured_user_email
    backend = construct_backend()
    user = user or backend.users.get_automatic_user()

    echo.echo_info('Configuring computer {} for user {}.'.format(computer.name, user.email))
    if user.email != get_configured_user_email():
        echo.echo_info('Configuring different user, defaults may not be appropriate.')

    configure_computer(computer, user=user, **kwargs)
    echo.echo_success('{} successfully configured for {}'.format(computer.name, user.email))
Esempio n. 21
0
def get_computer_configuration(computer, user=None):
    """Get the configuratio of computer for user as a dictionary."""
    from aiida.orm.backend import construct_backend

    backend = construct_backend()
    user = user or backend.users.get_automatic_user()

    config = {}
    try:
        authinfo = backend.authinfos.get(computer, user)
        config = authinfo.get_auth_params()
    except NotExistent:
        pass
    return config
Esempio n. 22
0
    def __init__(self, **kwargs):
        from aiida.orm.backend import construct_backend
        super(Group, self).__init__()

        self._backend = construct_backend()

        given_dbgroup = kwargs.pop('dbgroup', None)

        if given_dbgroup is not None:

            # Check that there is no other parameter passed besides dbgroup
            if kwargs:
                raise ValueError("If you pass a dbgroups, you cannot pass any "
                                 "further parameter")

            if isinstance(given_dbgroup, (int, long)):
                dbgroup_res = DbGroup.query.filter_by(id=given_dbgroup).first()
                if not dbgroup_res:
                    raise NotExistent("Group with pk={} does not exist".format(
                        given_dbgroup))
                dbgroup = dbgroup_res
            elif isinstance(given_dbgroup, DbGroup):
                dbgroup = given_dbgroup
            else:
                raise ValueError("Unrecognised inputs '{}'".format(kwargs))
        else:
            name = kwargs.pop('name', None)
            if name is None:
                raise ValueError("You have to specify a group name")
            group_type = kwargs.pop('type_string',
                                    "")  # By default, an user group

            # Get the user and extract the dbuser instance
            user = kwargs.pop('user', self._backend.users.get_automatic_user())
            user = user.dbuser

            description = kwargs.pop('description', "")

            if kwargs:
                raise ValueError("Too many parameters passed to Group, the "
                                 "unknown parameters are: {}".format(", ".join(
                                     kwargs.keys())))

            dbgroup = DbGroup(name=name,
                              description=description,
                              user=user,
                              type=group_type)

        self._dbgroup = utils.ModelWrapper(dbgroup)
Esempio n. 23
0
    def convert(self, value, param, ctx):
        from aiida.orm.backend import construct_backend

        backend = construct_backend()
        results = backend.users.find(email=value)

        if not results:
            if self._create:
                return backend.users.create(email=value)
            else:
                self.fail("User '{}' not found".format(value), param, ctx)
        elif len(results) > 1:
            self.fail("Multiple users found with email '{}': {}".format(
                value, results))

        return results[0]
Esempio n. 24
0
 def get_default(ctx):
     """Determine the default value from the context."""
     from aiida.orm.backend import construct_backend
     backend = construct_backend()
     user = ctx.params['user'] or backend.users.get_automatic_user()
     computer = ctx.params['computer']
     try:
         authinfo = backend.authinfos.get(computer=computer, user=user)
     except NotExistent:
         authinfo = backend.authinfos.create(computer=computer, user=user)
     non_interactive = ctx.params['non_interactive']
     old_authparams = authinfo.get_auth_params()
     if not also_noninteractive and non_interactive:
         raise click.MissingParameter()
     suggestion = old_authparams.get(key)
     suggestion = suggestion or transport_option_default(key, computer)
     return suggestion
Esempio n. 25
0
def add(comment, nodes):
    """
    Add comment to one or more nodes in the database
    """
    from aiida.orm.backend import construct_backend

    backend = construct_backend()
    user = backend.users.get_automatic_user()

    if not comment:
        comment = multi_line_input.edit_comment()

    for node in nodes:
        node.add_comment(comment, user)

    echo.echo_info("Comment added to node(s) '{}'".format(", ".join(
        [str(node.pk) for node in nodes])))
Esempio n. 26
0
def create_authinfo(computer):
    """
    Allow the current user to use the given computer.
    Deal with backwards compatibility down to aiida 0.11
    """
    from aiida import load_profile
    load_profile()
    from aiida.orm import backend as orm_backend
    authinfo = None
    if hasattr(orm_backend, 'construct_backend'):
        backend = orm_backend.construct_backend()
        authinfo = backend.authinfos.create(computer=computer,
                                            user=get_current_user())
    else:
        from aiida.backends.djsite.db.models import DbAuthInfo
        authinfo = DbAuthInfo(dbcomputer=computer.dbcomputer,
                              aiidauser=get_current_user())
    return authinfo
Esempio n. 27
0
    def __init__(self, **kwargs):
        """
        Initializes the Workflow super class, store the instance in the DB and in case
        stores the starting parameters.

        If initialized with an uuid the Workflow is loaded from the DB, if not a new
        workflow is generated and added to the DB following the stack frameworks. This
        means that only modules inside aiida.workflows are allowed to implements
        the workflow super calls and be stored. The caller names, modules and files are
        retrieved from the stack.

        :param uuid: a string with the uuid of the object to be loaded.
        :param params: a dictionary of storable objects to initialize the specific workflow
        :raise: NotExistent: if there is no entry of the desired workflow kind with
                             the given uuid.
        """
        super(AbstractWorkflow, self).__init__()
        self._backend = construct_backend()
Esempio n. 28
0
 def setUp(self):
     """Prepare computer builder with common properties."""
     from aiida.orm.backend import construct_backend
     from aiida.control.computer import ComputerBuilder
     self.backend = construct_backend()
     self.user = self.backend.users.get_automatic_user()
     self.runner = CliRunner()
     self.comp_builder = ComputerBuilder(label='test_comp_setup')
     self.comp_builder.hostname = 'localhost'
     self.comp_builder.description = 'Test Computer'
     self.comp_builder.enabled = True
     self.comp_builder.scheduler = 'direct'
     self.comp_builder.work_dir = '/tmp/aiida'
     self.comp_builder.prepend_text = ''
     self.comp_builder.append_text = ''
     self.comp_builder.mpiprocs_per_machine = 8
     self.comp_builder.mpirun_command = 'mpirun'
     self.comp_builder.shebang = '#!xonsh'
Esempio n. 29
0
    def __init__(self, **kwargs):
        from aiida.backends.djsite.db.models import DbGroup
        from aiida.orm.backend import construct_backend

        self._backend = construct_backend()

        dbgroup = kwargs.pop('dbgroup', None)

        if dbgroup is not None:
            if kwargs:
                raise ValueError(
                    "If you pass a dbgroups, you cannot pass any further parameter"
                )

            if isinstance(dbgroup, (int, long)):
                try:
                    dbgroup = DbGroup.objects.get(pk=dbgroup)
                except ObjectDoesNotExist:
                    raise NotExistent(
                        "Group with pk={} does not exist".format(dbgroup))

            type_check(dbgroup, DbGroup)
            self._dbgroup = utils.ModelWrapper(dbgroup)
        else:
            name = kwargs.pop('name', None)
            if name is None:
                raise ValueError("You have to specify a group name")

            group_type = kwargs.pop('type_string',
                                    "")  # By default, a user group

            # Get the user and extract dbuser instance
            user = kwargs.pop('user', self._backend.users.get_automatic_user())

            description = kwargs.pop('description', "")
            self._dbgroup = utils.ModelWrapper(
                DbGroup(name=name,
                        description=description,
                        user=user.dbuser,
                        type=group_type))
            if kwargs:
                raise ValueError("Too many parameters passed to Group, the "
                                 "unknown parameters are: {}".format(", ".join(
                                     kwargs.keys())))
Esempio n. 30
0
def query(datatype, project, past_days, group_pks, all_users):
    """
    Perform the query
    """
    import datetime

    from aiida.orm.implementation import Group
    from aiida.orm.user import User
    from aiida.orm.backend import construct_backend
    from aiida.orm.querybuilder import QueryBuilder
    from aiida.utils import timezone

    backend = construct_backend()

    qbl = QueryBuilder()
    if all_users is False:
        user = backend.users.get_automatic_user()
        qbl.append(User, tag="creator", filters={"email": user.email})
    else:
        qbl.append(User, tag="creator")

    # If there is a time restriction
    data_filters = {}
    if past_days is not None:
        now = timezone.now()
        n_days_ago = now - datetime.timedelta(days=past_days)
        data_filters.update({"ctime": {'>=': n_days_ago}})

    qbl.append(datatype, tag="data", created_by="creator", filters=data_filters, project=project)

    # If there is a group restriction
    if group_pks is not None:
        group_filters = dict()
        group_filters.update({"id": {"in": group_pks}})
        qbl.append(Group, tag="group", filters=group_filters, group_of="data")

    qbl.order_by({datatype: {'ctime': 'asc'}})

    object_list = qbl.distinct()
    return object_list.all()