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)
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)
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)
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)
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)