Esempio n. 1
0
def quicksetup(self, profile, email, first_name, last_name, institution,
               backend, db_port, db_user, db_user_pw, db_name, repo,
               set_default, non_interactive):
    '''Set up a sane aiida configuration with as little interaction as possible.'''
    from aiida.common.setup import create_base_dirs, AIIDA_CONFIG_FOLDER
    create_base_dirs()

    aiida_dir = os.path.expanduser(AIIDA_CONFIG_FOLDER)

    # access postgres
    postgres = Postgres(port=db_port,
                        interactive=bool(not non_interactive),
                        quiet=False)
    postgres.set_setup_fail_callback(prompt_db_info)
    success = postgres.determine_setup()
    if not success:
        sys.exit(1)

    # default database name is <profile>_<login-name>
    # this ensures that for profiles named test_... the database will also
    # be named test_...
    import getpass
    osuser = getpass.getuser()
    dbname = db_name or profile + '_' + osuser

    # default database user name is aiida_qs_<login-name>
    # default password is random
    dbuser = db_user or 'aiida_qs_' + osuser
    from aiida.common.setup import generate_random_secret_key
    dbpass = db_user_pw or generate_random_secret_key()

    # check if there is a profile that contains the db user already
    # and if yes, take the db user password from there
    # This is ok because a user can only see his own config files
    from aiida.common.setup import (set_default_profile, get_or_create_config)
    confs = get_or_create_config()
    profs = confs.get('profiles', {})
    for v in profs.itervalues():
        if v.get('AIIDADB_USER', '') == dbuser and not db_user_pw:
            dbpass = v.get('AIIDADB_PASS')
            print 'using found password for {}'.format(dbuser)
            break

    try:
        create = True
        if not postgres.dbuser_exists(dbuser):
            postgres.create_dbuser(dbuser, dbpass)
        else:
            dbname, create = _check_db_name(dbname, postgres)
        if create:
            postgres.create_db(dbuser, dbname)
    except Exception as e:
        click.echo('\n'.join([
            'Oops! Something went wrong while creating the database for you.',
            'You may continue with the quicksetup, however:',
            'For aiida to work correctly you will have to do that yourself as follows.',
            manual_setup_instructions(dbuser=dbuser, dbname=dbname), '',
            'Or setup your (OS-level) user to have permissions to create databases and rerun quicksetup.',
            ''
        ]))
        raise e

    # create a profile, by default 'quicksetup' and prompt the user if
    # already exists
    confs = get_or_create_config()
    profile_name = profile or 'quicksetup'
    write_profile = False
    while not write_profile:
        if profile_name in confs.get('profiles', {}):
            if click.confirm(
                    'overwrite existing profile {}?'.format(profile_name)):
                write_profile = True
            else:
                profile_name = click.prompt('new profile name', type=str)
        else:
            write_profile = True

    dbhost = postgres.dbinfo.get('host', 'localhost')
    dbport = postgres.dbinfo.get('port', '5432')

    from os.path import isabs
    repo = repo or 'repository-{}/'.format(profile_name)
    if not isabs(repo):
        repo = os.path.join(aiida_dir, repo)

    setup_args = {
        'backend': backend,
        'email': email,
        'db_host': dbhost,
        'db_port': dbport,
        'db_name': dbname,
        'db_user': dbuser,
        'db_pass': dbpass,
        'repo': repo,
        'first_name': first_name,
        'last_name': last_name,
        'institution': institution,
        'force_overwrite': write_profile,
    }
    setup(profile_name, only_config=False, non_interactive=True, **setup_args)

    # Loop over all valid processes and check if a default profile is set for them
    # If not set the newly created profile as default, otherwise prompt whether to override
    from aiida.cmdline.commands.profile import valid_processes

    default_profiles = confs.get('default_profiles', {})

    for process in valid_processes:

        # if the user specifies whether to override that's fine
        if set_default in [True, False]:
            _set_default = set_default
        # otherwise we may need to ask
        else:
            default_profile = default_profiles.get(process, '')
            if default_profile:
                _set_default = click.confirm(
                    "The default profile for the '{}' process is set to '{}': "
                    "do you want to set the newly created '{}' as the new default? (can be reverted later)"
                    .format(process, default_profile, profile_name))
            # if there are no other default profiles, we don't need to ask
            else:
                _set_default = True

        if _set_default:
            set_default_profile(process, profile_name, force_rewrite=True)
Esempio n. 2
0
    def _quicksetup_cmd(self, email, first_name, last_name, institution,
                        backend, db_port, db_user, db_user_pw, db_name,
                        profile, repo):
        '''setup a sane aiida configuration with as little interaction as possible.'''
        from aiida.common.setup import create_base_dirs, AIIDA_CONFIG_FOLDER
        create_base_dirs()

        aiida_dir = os.path.expanduser(AIIDA_CONFIG_FOLDER)

        # access postgres
        pg_info = self._get_pg_access()
        pg_execute = pg_info['method']
        dbinfo = pg_info['dbinfo']

        # check if a database setup already exists
        # otherwise setup the database user aiida
        # setup the database aiida_qs_<username>
        from getpass import getuser
        from aiida.common.setup import generate_random_secret_key
        osuser = getuser()
        dbuser = db_user or 'aiida_qs_' + osuser
        dbpass = db_user_pw or generate_random_secret_key()
        dbname = db_name or 'aiidadb_qs_' + osuser

        # check if there is a profile that contains the db user already
        # and if yes, take the db user password from there
        # This is ok because a user can only see his own config files
        from aiida.common.setup import (set_default_profile,
                                        get_or_create_config)
        confs = get_or_create_config()
        profs = confs.get('profiles', {})
        for v in profs.itervalues():
            if v.get('AIIDADB_USER', '') == dbuser and not db_user_pw:
                dbpass = v.get('AIIDADB_PASS')
                print 'using found password for {}'.format(dbuser)
                break

        try:
            create = True
            if not self._dbuser_exists(dbuser, pg_execute, **dbinfo):
                self._create_dbuser(dbuser, dbpass, pg_execute, **dbinfo)
            else:
                dbname, create = self._check_db_name(dbname, pg_execute,
                                                     **dbinfo)
            if create:
                self._create_db(dbuser, dbname, pg_execute, **dbinfo)
        except Exception as e:
            click.echo('\n'.join([
                'Oops! Something went wrong while creating the database for you.',
                'You may continue with the quicksetup, however:',
                'For aiida to work correctly you will have to do that yourself as follows.',
                'Please run the following commands as the user for PostgreSQL (Ubuntu: $sudo su postgres):',
                '', '\t$ psql template1',
                '\t==> ' + self._create_user_command.format(dbuser, dbpass),
                '\t==> ' + self._create_db_command.format(dbname, dbuser),
                '\t==> ' + self._grant_priv_command.format(dbname, dbuser), '',
                'Or setup your (OS-level) user to have permissions to create databases and rerun quicksetup.',
                ''
            ]))
            raise e

        # create a profile, by default 'quicksetup' and prompt the user if
        # already exists
        profile_name = profile or 'quicksetup'
        write_profile = False
        confs = get_or_create_config()
        profile_name = profile or 'quicksetup'
        write_profile = False
        while not write_profile:
            if profile_name in confs.get('profiles', {}):
                if click.confirm(
                        'overwrite existing profile {}?'.format(profile_name)):
                    write_profile = True
                else:
                    profile_name = click.prompt('new profile name', type=str)
            else:
                write_profile = True

        dbhost = dbinfo.get('host', 'localhost')
        dbport = dbinfo.get('port', '5432')

        from os.path import isabs
        repo = repo or 'repository-{}/'.format(profile_name)
        if not isabs(repo):
            repo = os.path.join(aiida_dir, repo)

        setup_args = {
            'backend': backend,
            'email': email,
            'db_host': dbhost,
            'db_port': dbport,
            'db_name': dbname,
            'db_user': dbuser,
            'db_pass': dbpass,
            'repo': repo,
            'first_name': first_name,
            'last_name': last_name,
            'institution': institution,
            'force_overwrite': write_profile,
        }
        setup(profile_name,
              only_config=False,
              non_interactive=True,
              **setup_args)

        # Loop over all valid processes and check if a default profile is set for them
        # If not set the newly created profile as default, otherwise prompt whether to override
        from aiida.cmdline.commands.profile import valid_processes

        default_profiles = confs.get('default_profiles', {})

        for process in valid_processes:

            default_profile = default_profiles.get(process, '')
            default_override = False

            if default_profile:
                default_override = click.confirm(
                    "The default profile for the '{}' process is set to '{}': "
                    "do you want to set the newly created '{}' as the new default? (can be reverted later)"
                    .format(process, default_profile, profile_name))

            if not default_profile or default_override:
                set_default_profile(process, profile_name, force_rewrite=True)
Esempio n. 3
0
    def profile_delete(self, *args):
        """ Deletes profile

        Asks whether to delete associated database and associated database
        user.

        Specify argument '--force' to skip any questions warning about loss of
        data.
        """
        from aiida.common.setup import get_or_create_config, update_config
        import os.path
        from urlparse import urlparse

        args = list(args)
        if '--force' in args:
            force = True
            args.remove('--force')
        else:
            force = False

        confs = get_or_create_config()
        profiles = confs.get('profiles', {})
        users = [
            profiles[name].get('AIIDADB_USER', '') for name in profiles.keys()
        ]

        profiles_to_delete = args
        for profile_to_delete in profiles_to_delete:
            try:
                profile = profiles[profile_to_delete]
            except KeyError:
                print("Profile '{}' does not exist".format(profile_to_delete))
                continue

            postgres = Postgres(port=profile.get('AIIDADB_PORT'),
                                interactive=True,
                                quiet=False)
            postgres.determine_setup()
            print postgres.dbinfo

            db_name = profile.get('AIIDADB_NAME', '')
            if not postgres.db_exists(db_name):
                print(
                    "Associated database '{}' does not exist.".format(db_name))
            elif force or click.confirm("Delete associated database '{}'?\n" \
                             "WARNING: All data will be lost.".format(db_name)):
                print("Deleting database '{}'.".format(db_name))
                postgres.drop_db(db_name)

            user = profile.get('AIIDADB_USER', '')
            if not postgres.dbuser_exists(user):
                print("Associated database user '{}' does not exist.".format(
                    user))
            elif users.count(user) > 1:
                print("Associated database user '{}' is used by other profiles "\
                      "and will not be deleted.".format(user))
            elif force or click.confirm(
                    "Delete database user '{}'?".format(user)):
                print("Deleting user '{}'.".format(user))
                postgres.drop_dbuser(user)

            repo_uri = profile.get('AIIDADB_REPOSITORY_URI', '')
            repo_path = urlparse(repo_uri).path
            repo_path = os.path.expanduser(repo_path)
            if not os.path.isabs(repo_path):
                print("Associated file repository '{}' does not exist."\
                      .format(repo_path))
            elif not os.path.isdir(repo_path):
                print("Associated file repository '{}' is not a directory."\
                       .format(repo_path))
            elif force or click.confirm("Delete associated file repository '{}'?\n" \
                               "WARNING: All data will be lost.".format(repo_path)):
                print("Deleting directory '{}'.".format(repo_path))
                import shutil
                shutil.rmtree(repo_path)

            if force or click.confirm("Delete configuration for profile '{}'?\n" \
                             "WARNING: Permanently removes profile from the list of AiiDA profiles."\
                             .format(profile_to_delete)):
                print("Deleting configuration for profile '{}'.".format(
                    profile_to_delete))
                del profiles[profile_to_delete]
                update_config(confs)
Esempio n. 4
0
def quicksetup(profile_name, only_config, set_default, non_interactive, backend, db_host, db_port, db_name, db_username,
               db_password, repository, email, first_name, last_name, institution):
    """Set up a sane configuration with as little interaction as possible."""
    from aiida.common.setup import create_base_dirs, AIIDA_CONFIG_FOLDER
    create_base_dirs()

    aiida_dir = os.path.expanduser(AIIDA_CONFIG_FOLDER)

    # access postgres
    postgres = Postgres(host=db_host, port=db_port, interactive=bool(not non_interactive), quiet=False)
    postgres.set_setup_fail_callback(prompt_db_info)
    success = postgres.determine_setup()
    if not success:
        sys.exit(1)

    # default database name is <profile_name>_<login-name>
    # this ensures that for profiles named test_... the database will also
    # be named test_...
    import getpass
    osuser = getpass.getuser()
    dbname = db_name or profile_name + '_' + osuser

    # default database user name is aiida_qs_<login-name>
    # default password is random
    dbuser = db_username or 'aiida_qs_' + osuser
    from aiida.common.setup import generate_random_secret_key
    dbpass = db_password or generate_random_secret_key()

    # check if there is a profile that contains the db user already
    # and if yes, take the db user password from there
    # This is ok because a user can only see his own config files
    from aiida.common.setup import get_or_create_config
    confs = get_or_create_config()
    profs = confs.get('profiles', {})
    for profile in profs.itervalues():
        if profile.get('AIIDADB_USER', '') == dbuser and not db_password:
            dbpass = profile.get('AIIDADB_PASS')
            print 'using found password for {}'.format(dbuser)
            break

    try:
        create = True
        if not postgres.dbuser_exists(dbuser):
            postgres.create_dbuser(dbuser, dbpass)
        else:
            dbname, create = _check_db_name(dbname, postgres)
        if create:
            postgres.create_db(dbuser, dbname)
    except Exception as exception:
        click.echo('\n'.join([
            'Oops! Something went wrong while creating the database for you.',
            'You may continue with the quicksetup, however:',
            'For aiida to work correctly you will have to do that yourself as follows.',
            manual_setup_instructions(dbuser=dbuser, dbname=dbname), '',
            'Or setup your (OS-level) user to have permissions to create databases and rerun quicksetup.', ''
        ]))
        raise exception

    # create a profile, by default 'quicksetup' and prompt the user if
    # already exists
    confs = get_or_create_config()
    profile_name = profile_name or 'quicksetup'
    write_profile = False
    while not write_profile:
        if profile_name in confs.get('profiles', {}):
            if click.confirm('overwrite existing profile {}?'.format(profile_name)):
                write_profile = True
            else:
                profile_name = click.prompt('new profile name', type=str)
        else:
            write_profile = True

    dbhost = postgres.dbinfo.get('host', 'localhost')
    dbport = postgres.dbinfo.get('port', '5432')

    from os.path import isabs
    repo = repository or 'repository-{}/'.format(profile_name)
    if not isabs(repo):
        repo = os.path.join(aiida_dir, repo)

    setup_args = {
        'backend': backend,
        'email': email,
        'db_host': dbhost,
        'db_port': dbport,
        'db_name': dbname,
        'db_user': dbuser,
        'db_pass': dbpass,
        'repo': repo,
        'first_name': first_name,
        'last_name': last_name,
        'institution': institution,
        'force_overwrite': write_profile,
    }

    setup_profile(profile_name, only_config=only_config, set_default=set_default, non_interactive=True, **setup_args)
Esempio n. 5
0
def profile_delete(force, profiles):
    """
    Delete PROFILES separated by space from aiida config file
    along with its associated database and repository.
    """
    from aiida.common.setup import get_or_create_config, update_config
    import os.path
    from urlparse import urlparse

    echo.echo('profiles: {}'.format(', '.join(profiles)))

    confs = get_or_create_config()
    available_profiles = confs.get('profiles', {})
    users = [
        available_profiles[name].get('AIIDADB_USER', '')
        for name in available_profiles.keys()
    ]

    for profile_name in profiles:
        try:
            profile = available_profiles[profile_name]
        except KeyError:
            echo.echo_info("Profile '{}' does not exist".format(profile_name))
            continue

        postgres = Postgres(port=profile.get('AIIDADB_PORT'),
                            interactive=True,
                            quiet=False)
        postgres.dbinfo["user"] = profile.get('AIIDADB_USER')
        postgres.dbinfo["host"] = profile.get('AIIDADB_HOST')
        postgres.determine_setup()

        import json
        echo.echo(json.dumps(postgres.dbinfo, indent=4))

        db_name = profile.get('AIIDADB_NAME', '')
        if not postgres.db_exists(db_name):
            echo.echo_info(
                "Associated database '{}' does not exist.".format(db_name))
        elif force or click.confirm("Delete associated database '{}'?\n" \
                                    "WARNING: All data will be lost.".format(db_name)):
            echo.echo_info("Deleting database '{}'.".format(db_name))
            postgres.drop_db(db_name)

        user = profile.get('AIIDADB_USER', '')
        if not postgres.dbuser_exists(user):
            echo.echo_info(
                "Associated database user '{}' does not exist.".format(user))
        elif users.count(user) > 1:
            echo.echo_info("Associated database user '{}' is used by other profiles " \
                  "and will not be deleted.".format(user))
        elif force or click.confirm("Delete database user '{}'?".format(user)):
            echo.echo_info("Deleting user '{}'.".format(user))
            postgres.drop_dbuser(user)

        repo_uri = profile.get('AIIDADB_REPOSITORY_URI', '')
        repo_path = urlparse(repo_uri).path
        repo_path = os.path.expanduser(repo_path)
        if not os.path.isabs(repo_path):
            echo.echo_info("Associated file repository '{}' does not exist." \
                  .format(repo_path))
        elif not os.path.isdir(repo_path):
            echo.echo_info("Associated file repository '{}' is not a directory." \
                  .format(repo_path))
        elif force or click.confirm("Delete associated file repository '{}'?\n" \
                                    "WARNING: All data will be lost.".format(repo_path)):
            echo.echo_info("Deleting directory '{}'.".format(repo_path))
            import shutil
            shutil.rmtree(repo_path)

        if force or click.confirm("Delete configuration for profile '{}'?\n" \
                                  "WARNING: Permanently removes profile from the list of AiiDA profiles." \
                                          .format(profile_name)):
            echo.echo_info("Deleting configuration for profile '{}'.".format(
                profile_name))
            del available_profiles[profile_name]
            update_config(confs)