def setUp(self): """Set up a temporary database cluster for testing potentially destructive operations""" self.pg_test = PGTest() self.postgres = Postgres(port=self.pg_test.port, interactive=False, quiet=True) self.dbuser = '******' self.dbpass = '******' self.dbname = 'aiida_db'
def setUp(self): self.runner = CliRunner() backend = os.environ.get('TEST_AIIDA_BACKEND', 'django') self.backend = 'django' if backend == 'django' else 'sqlalchemy' self.pg_test = PGTest() self.postgres = Postgres(port=self.pg_test.port, interactive=False, quiet=True) self.postgres.dbinfo = self.pg_test.dsn self.postgres.determine_setup() self.dbuser = '******' self.dbpass = '******' self.dbname = 'aiida_test_setup' self.postgres.create_dbuser(self.dbuser, self.dbpass) self.postgres.create_db(self.dbuser, self.dbname) self.repo = abspath('./aiida_radames')
def create_aiida_db(self): """Create the necessary database on the temporary postgres instance""" if is_dbenv_loaded(): raise FixtureError('AiiDA dbenv can not be loaded while creating a test db environment') if not self.db_params: self.create_db_cluster() self.postgres = Postgres(interactive=False, quiet=True) self.postgres.dbinfo = self.db_params self.postgres.determine_setup() self.db_params = self.postgres.dbinfo if not self.postgres.pg_execute: raise FixtureError('Could not connect to the test postgres instance') self.postgres.create_dbuser(self.db_user, self.db_pass) self.postgres.create_db(self.db_user, self.db_name) self.__is_running_on_test_db = True
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(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(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 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)