-
Notifications
You must be signed in to change notification settings - Fork 192
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CLI: Add the command
verdi presto
(#6351)
This command aims making setting up a new profile as easy as possible. It intentionally provides a limited amount of options to customize the profile and by default does not require any options to be specified at all. For full control, the command `verdi profile setup` should be used instead. The main goal for this command is to setup a profile with minimal requirements to make it easy to install AiiDA and get started as quickly as possible. Therefore, by default, the created profile uses the `core.sqlite_dos` storage plugin which does not require any services, such as PostgreSQL and RabbitMQ are not required. This _does_ mean, however, that not all functionality of AiiDA is available, most notably running the daemon and submitting processes to said daemon. The command performs the following actions: * Create a new profile that is set as the new default * Create a default user for the profile (can be configured through options) * Set up the localhost as a `Computer` and configure it * Set a number of configuration options with sensible defaults In the future, it may be possible to incorporate the functionality of the `verdi quicksetup` command that automatically creates the role and database in PostgreSQL necessary for a profile with the `core.psql_dos` storage plugin. This would allow `verdi quicksetup` to be retired leaving just `verdi presto` and `verdi profile setup` to provide all the profile setup needs.
- Loading branch information
Showing
9 changed files
with
254 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ | |
cmd_help, | ||
cmd_node, | ||
cmd_plugin, | ||
cmd_presto, | ||
cmd_process, | ||
cmd_profile, | ||
cmd_rabbitmq, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
########################################################################### | ||
# Copyright (c), The AiiDA team. All rights reserved. # | ||
# This file is part of the AiiDA code. # | ||
# # | ||
# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core # | ||
# For further information on the license, see the LICENSE.txt file # | ||
# For further information please visit http://www.aiida.net # | ||
########################################################################### | ||
"""``verdi presto`` command.""" | ||
|
||
from __future__ import annotations | ||
|
||
import pathlib | ||
import re | ||
import typing as t | ||
|
||
import click | ||
|
||
from aiida.cmdline.commands.cmd_verdi import verdi | ||
from aiida.cmdline.utils import echo | ||
from aiida.manage.configuration import get_config_option | ||
|
||
DEFAULT_PROFILE_NAME_PREFIX: str = 'presto' | ||
|
||
|
||
def get_default_presto_profile_name(): | ||
from aiida.manage import get_config | ||
|
||
profile_names = get_config().profile_names | ||
indices = [] | ||
|
||
for profile_name in profile_names: | ||
if match := re.search(r'presto[-]?(\d+)?', profile_name): | ||
indices.append(match.group(1) or '0') | ||
|
||
if not indices: | ||
return DEFAULT_PROFILE_NAME_PREFIX | ||
|
||
last_index = int(sorted(indices)[-1]) | ||
|
||
return f'{DEFAULT_PROFILE_NAME_PREFIX}-{last_index + 1}' | ||
|
||
|
||
@verdi.command('presto') | ||
@click.option( | ||
'--profile-name', | ||
default=lambda: get_default_presto_profile_name(), | ||
show_default=True, | ||
help=f'Name of the profile. By default, a unique name starting with `{DEFAULT_PROFILE_NAME_PREFIX}` is ' | ||
'automatically generated.', | ||
) | ||
@click.option( | ||
'--email', | ||
default=get_config_option('autofill.user.email') or 'aiida@localhost', | ||
show_default=True, | ||
help='Email of the default user.', | ||
) | ||
@click.pass_context | ||
def verdi_presto(ctx, profile_name, email): | ||
"""Set up a new profile in a jiffy. | ||
This command aims to make setting up a new profile as easy as possible. It intentionally provides only a limited | ||
amount of options to customize the profile and by default does not require any options to be specified at all. For | ||
full control, please use `verdi profile setup`. | ||
After running `verdi presto` you can immediately start using AiiDA without additional setup. The created profile | ||
uses the `core.sqlite_dos` storage plugin which does not require any services, such as PostgreSQL. The broker | ||
service RabbitMQ is also optional. The command tries to connect to it using default settings and configures it for | ||
the profile if found. Otherwise, the profile is created without a broker, in which case some functionality will be | ||
unavailable, most notably running the daemon and submitting processes to said daemon. | ||
The command performs the following actions: | ||
\b | ||
* Create a new profile that is set as the new default | ||
* Create a default user for the profile (email can be configured through the `--email` option) | ||
* Set up the localhost as a `Computer` and configure it | ||
* Set a number of configuration options with sensible defaults | ||
""" | ||
from aiida.brokers.rabbitmq.defaults import detect_rabbitmq_config | ||
from aiida.common import exceptions | ||
from aiida.manage.configuration import create_profile, load_profile | ||
from aiida.orm import Computer | ||
|
||
storage_config: dict[str, t.Any] = {} | ||
storage_backend = 'core.sqlite_dos' | ||
|
||
broker_config = detect_rabbitmq_config() | ||
broker_backend = 'core.rabbitmq' if broker_config is not None else None | ||
|
||
if broker_config is None: | ||
echo.echo_report('RabbitMQ server not found: configuring the profile without a broker.') | ||
else: | ||
echo.echo_report('RabbitMQ server detected: configuring the profile with a broker.') | ||
|
||
try: | ||
profile = create_profile( | ||
ctx.obj.config, | ||
name=profile_name, | ||
email=email, | ||
storage_backend=storage_backend, | ||
storage_config=storage_config, | ||
broker_backend=broker_backend, | ||
broker_config=broker_config, | ||
) | ||
except (ValueError, TypeError, exceptions.EntryPointError, exceptions.StorageMigrationError) as exception: | ||
echo.echo_critical(str(exception)) | ||
|
||
echo.echo_success(f'Created new profile `{profile.name}`.') | ||
|
||
ctx.obj.config.set_option('runner.poll.interval', 1, scope=profile.name) | ||
ctx.obj.config.set_default_profile(profile.name, overwrite=True) | ||
ctx.obj.config.store() | ||
|
||
load_profile(profile.name, allow_switch=True) | ||
echo.echo_info(f'Loaded newly created profile `{profile.name}`.') | ||
|
||
filepath_scratch = pathlib.Path(ctx.obj.config.dirpath) / 'scratch' / profile.name | ||
|
||
computer = Computer( | ||
label='localhost', | ||
hostname='localhost', | ||
description='Localhost automatically created by `verdi presto`', | ||
transport_type='core.local', | ||
scheduler_type='core.direct', | ||
workdir=str(filepath_scratch), | ||
).store() | ||
computer.configure(safe_interval=0) | ||
computer.set_minimum_job_poll_interval(1) | ||
computer.set_default_mpiprocs_per_machine(1) | ||
|
||
echo.echo_success('Configured the localhost as a computer.') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
"""Tests for ``verdi presto``.""" | ||
|
||
import pytest | ||
from aiida.cmdline.commands.cmd_presto import get_default_presto_profile_name, verdi_presto | ||
from aiida.manage.configuration import profile_context | ||
from aiida.manage.configuration.config import Config | ||
from aiida.orm import Computer | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'profile_names, expected', | ||
( | ||
([], 'presto'), | ||
(['main', 'sqlite'], 'presto'), | ||
(['presto'], 'presto-1'), | ||
(['presto', 'presto-5', 'presto-2'], 'presto-6'), | ||
(['presto', 'main', 'presto-2', 'sqlite'], 'presto-3'), | ||
), | ||
) | ||
def test_get_default_presto_profile_name(monkeypatch, profile_names, expected): | ||
"""Test the dynamic default profile function.""" | ||
|
||
def get_profile_names(self): | ||
return profile_names | ||
|
||
monkeypatch.setattr(Config, 'profile_names', property(get_profile_names)) | ||
assert get_default_presto_profile_name() == expected | ||
|
||
|
||
@pytest.mark.usefixtures('empty_config') | ||
@pytest.mark.parametrize('with_broker', (True, False)) | ||
def test_presto(run_cli_command, with_broker, monkeypatch): | ||
"""Test the ``verdi presto``.""" | ||
from aiida.brokers.rabbitmq import defaults | ||
|
||
if not with_broker: | ||
# Patch the RabbitMQ detection function to pretend it could not find the service | ||
monkeypatch.setattr(defaults, 'detect_rabbitmq_config', lambda: None) | ||
|
||
result = run_cli_command(verdi_presto) | ||
assert 'Created new profile `presto`.' in result.output | ||
|
||
with profile_context('presto', allow_switch=True) as profile: | ||
assert profile.name == 'presto' | ||
localhost = Computer.collection.get(label='localhost') | ||
assert localhost.is_configured | ||
if with_broker: | ||
assert profile.process_control_backend == 'core.rabbitmq' | ||
else: | ||
assert profile.process_control_backend is None |