def setUpClass(cls): from aiida.orm.user import User from aiida.orm.computer import Computer from aiida.common.utils import get_configured_user_email # I create the user only once: # We create the user only once: # Otherwise, get_automatic_user() will fail when the # user is recreated because it caches the user! # In any case, store it in cls.user though # Other possibility: flush the user cache on delete users = User.search_for_users(email=get_configured_user_email()) assert (len(users) <= 1) if users: cls.user = users[0] else: cls.user = User(get_configured_user_email()) cls.user.password = '******' cls.user.save() try: cls.computer = Computer.get('test_comp') except NotExistent: cls.computer = Computer(name='test_comp', hostname='localhost', transport_type='local', scheduler_type='pbspro', workdir='/tmp/aiida') cls.computer.store()
def get_schema(self): # Construct the full class string class_string = 'aiida.orm.' + self._aiida_type # Load correspondent orm class orm_class = get_object_from_string(class_string) # Construct the json object to be returned basic_schema = orm_class.get_schema() schema = {} ordering = [] # get addional info and column order from translator class # and combine it with basic schema if len(self._schema_projections["column_order"]) > 0: for field in self._schema_projections["column_order"]: # basic schema if field in basic_schema.keys(): schema[field] = basic_schema[field] else: ## Note: if column name starts with user_* get the schema information from # user class. It is added mainly to handle user_email case. # TODO need to improve field_parts = field.split("_") if field_parts[0] == "user" and field != "user_id" and len( field_parts) > 1: from aiida.orm.user import User user_schema = User.get_schema() if field_parts[1] in user_schema.keys(): schema[field] = user_schema[field_parts[1]] else: raise KeyError( "{} is not present in user schema".format( field)) else: raise KeyError( "{} is not present in ORM basic schema".format( field)) # additional info defined in translator class if field in self._schema_projections["additional_info"]: schema[field].update( self._schema_projections["additional_info"][field]) else: raise KeyError( "{} is not present in default projection additional info" .format(field)) # order ordering = self._schema_projections["column_order"] else: raise ConfigurationError( "Define column order to get schema for {}".format( self._aiida_type)) return dict(fields=schema, ordering=ordering)
def test_session_update_and_expiration_2(self): """ expire_on_commit=True & committing computer and code objects with their built-in store function. """ from aiida.backends.sqlalchemy.models.user import DbUser from aiida.orm.computer import Computer from aiida.orm.code import Code from aiida.orm.user import User session = aiida.backends.sqlalchemy.get_scoped_session() self.set_connection(expire_on_commit=True) user = User(email=get_configured_user_email()) session.add(user._dbuser) session.commit() defaults = dict(name='localhost', hostname='localhost', transport_type='local', scheduler_type='pbspro', workdir='/tmp/aiida') computer = Computer(**defaults) computer.store() code = Code() code.set_remote_computer_exec((computer, '/x.x')) code.store() self.drop_connection()
def test_session_update_and_expiration_3(self): """ expire_on_commit=False & adding manually and committing computer and code objects. """ from aiida.orm.computer import Computer from aiida.orm.code import Code from aiida.orm.user import User self.set_connection(expire_on_commit=False) session = aiida.backends.sqlalchemy.get_scoped_session() user = User(email=get_configured_user_email()) session.add(user._dbuser) session.commit() defaults = dict(name='localhost', hostname='localhost', transport_type='local', scheduler_type='pbspro', workdir='/tmp/aiida') computer = Computer(**defaults) session.add(computer._dbcomputer) session.commit() code = Code() code.set_remote_computer_exec((computer, '/x.x')) session.add(code.dbnode) session.commit() self.drop_connection()
def setUpClass(cls, *args, **kwargs): """ Create some data needed for the tests """ super(TestVerdiDataCommands, cls).setUpClass() from aiida.orm.user import User from aiida.orm.group import Group # Create a secondary user new_email = "[email protected]" new_user = User(email=new_email) new_user.force_save() # Create a group to add specific data inside g1 = Group(name=cls.group_name) g1.store() cls.group_id = g1.id cls.create_bands_data(cls.cmd_to_nodeid_map, cls.cmd_to_nodeid_map_for_groups, cls.cmd_to_nodeid_map_for_nuser, g1, new_user) cls.create_structure_data(cls.cmd_to_nodeid_map, cls.cmd_to_nodeid_map_for_groups, cls.cmd_to_nodeid_map_for_nuser, g1, new_user) cls.create_cif_data(cls.cmd_to_nodeid_map, cls.cmd_to_nodeid_map_for_groups, cls.cmd_to_nodeid_map_for_nuser, g1, new_user) cls.create_trajectory_data(cls.cmd_to_nodeid_map, cls.cmd_to_nodeid_map_for_groups, cls.cmd_to_nodeid_map_for_nuser, g1, new_user)
def computer_enable(self, *args): """ Enable a computer. """ if not is_dbenv_loaded(): load_dbenv() import argparse from django.core.exceptions import ObjectDoesNotExist from aiida.common.exceptions import NotExistent from aiida.orm.implementation import User parser = argparse.ArgumentParser(prog=self.get_full_command_name(), description='Enable a computer') # The default states are those that are shown if no option is given parser.add_argument( '-u', '--only-for-user', type=str, metavar='EMAIL', dest='user_email', help="Enable a computer only for the given user. " "If not specified, enables the computer " "globally.", ) parser.add_argument('computer', type=str, help="The name of the computer that you " "want to enable") parsed_args = parser.parse_args(args) user_email = parsed_args.user_email computername = parsed_args.computer try: computer = self.get_computer(name=computername) except NotExistent: print >> sys.stderr, "No computer exists with name '{}'".format( computername) sys.exit(1) if user_email is None: if computer.is_enabled(): print "Computer '{}' already enabled.".format(computername) else: computer.set_enabled_state(True) print "Computer '{}' enabled.".format(computername) else: user_list = User.search_for_users(email=user_email) if user_list is None or len(user_list) == 0: print >> sys.stderr, ("No user with email '{}' in the " "database.".format(user_email)) sys.exit(1) user = user_list[0] try: dbauthinfo = computer.get_dbauthinfo(user._dbuser) if not dbauthinfo.enabled: dbauthinfo.enabled = True dbauthinfo.save() print "Computer '{}' enabled for user {}.".format( computername, user.get_full_name()) else: print "Computer '{}' was already enabled for user {} {}.".format( computername, user.first_name, user.last_name) except NotExistent: print >> sys.stderr, ("User with email '{}' is not configured " "for computer '{}' yet.".format( user_email, computername)) sys.exit(1)
def run(self, *args): from aiida.common.setup import (create_base_dirs, create_configuration, set_default_profile, DEFAULT_UMASK) from aiida.backends.profile import BACKEND_SQLA, BACKEND_DJANGO from aiida.backends.utils import set_backend_type, get_backend_type from aiida.common.exceptions import InvalidOperation cmdline_args = list(args) only_user_config = False try: cmdline_args.remove('--only-config') only_user_config = True except ValueError: # Parameter not provided pass if cmdline_args: print >> sys.stderr, "Unknown parameters on the command line: " print >> sys.stderr, ", ".join(cmdline_args) sys.exit(1) # create the directories to store the configuration files create_base_dirs() # gprofile = 'default' if profile is None else profile gprofile = 'default' if settings_profile.AIIDADB_PROFILE is None \ else settings_profile.AIIDADB_PROFILE created_conf = None # ask and store the configuration of the DB try: created_conf = create_configuration(profile=gprofile) except ValueError as e: print >> sys.stderr, "Error during configuration: {}".format( e.message) sys.exit(1) # set default DB profiles set_default_profile('verdi', gprofile, force_rewrite=False) set_default_profile('daemon', gprofile, force_rewrite=False) if only_user_config: print( "Only user configuration requested, " "skipping the migrate command") else: print "Executing now a migrate command..." backend_choice = created_conf['AIIDADB_BACKEND'] if backend_choice == BACKEND_DJANGO: print("...for Django backend") # The correct profile is selected within load_dbenv. # Setting os.umask here since sqlite database gets created in # this step. old_umask = os.umask(DEFAULT_UMASK) # This check should be done more properly # try: # backend_type = get_backend_type() # except KeyError: # backend_type = None # # if backend_type is not None and backend_type != BACKEND_DJANGO: # raise InvalidOperation("An already existing database found" # "and a different than the selected" # "backend was used for its " # "management.") try: pass_to_django_manage([execname, 'migrate'], profile=gprofile) finally: os.umask(old_umask) set_backend_type(BACKEND_DJANGO) elif backend_choice == BACKEND_SQLA: print("...for SQLAlchemy backend") from aiida.backends.sqlalchemy.models.base import Base from aiida.backends.sqlalchemy.utils import (get_engine, install_tc) from aiida.common.setup import get_profile_config from aiida import is_dbenv_loaded, load_dbenv if not is_dbenv_loaded(): load_dbenv() # This check should be done more properly # try: # backend_type = get_backend_type() # except KeyError: # backend_type = None # # if backend_type is not None and backend_type != BACKEND_SQLA: # raise InvalidOperation("An already existing database found" # "and a different than the selected" # "backend was used for its " # "management.") # Those import are necessary for SQLAlchemy to correctly create # the needed database tables. from aiida.backends.sqlalchemy.models.authinfo import ( DbAuthInfo) from aiida.backends.sqlalchemy.models.comment import DbComment from aiida.backends.sqlalchemy.models.computer import ( DbComputer) from aiida.backends.sqlalchemy.models.group import ( DbGroup, table_groups_nodes) from aiida.backends.sqlalchemy.models.lock import DbLock from aiida.backends.sqlalchemy.models.log import DbLog from aiida.backends.sqlalchemy.models.node import (DbLink, DbNode, DbPath, DbCalcState) from aiida.backends.sqlalchemy.models.user import DbUser from aiida.backends.sqlalchemy.models.workflow import ( DbWorkflow, DbWorkflowData, DbWorkflowStep) from aiida.backends.sqlalchemy.models.settings import DbSetting connection = get_engine(get_profile_config(gprofile)) Base.metadata.create_all(connection) install_tc(connection) set_backend_type(BACKEND_SQLA) else: raise InvalidOperation("Not supported backend selected.") print "Database was created successfully" # I create here the default user print "Loading new environment..." if only_user_config: from aiida.backends.utils import load_dbenv, is_dbenv_loaded # db environment has not been loaded in this case if not is_dbenv_loaded(): load_dbenv() from aiida.common.setup import DEFAULT_AIIDA_USER from aiida.orm.user import User as AiiDAUser if not AiiDAUser.search_for_users(email=DEFAULT_AIIDA_USER): print "Installing default AiiDA user..." nuser = AiiDAUser(email=DEFAULT_AIIDA_USER) nuser.first_name = "AiiDA" nuser.last_name = "Daemon" nuser.is_staff = True nuser.is_active = True nuser.is_superuser = True nuser.force_save() from aiida.common.utils import get_configured_user_email email = get_configured_user_email() print "Starting user configuration for {}...".format(email) if email == DEFAULT_AIIDA_USER: print "You set up AiiDA using the default Daemon email ({}),".format( email) print "therefore no further user configuration will be asked." else: # Ask to configure the new user User().user_configure(email) print "Install finished."
def computer_disable(self, *args): """ Disable a computer. If a computer is disabled, AiiDA does not try to connect to it to submit new calculations or check for the state of existing calculations. Useful, for instance, if you know that a computer is under maintenance. """ if not is_dbenv_loaded(): load_dbenv() import argparse from aiida.common.exceptions import NotExistent parser = argparse.ArgumentParser(prog=self.get_full_command_name(), description='Disable a computer') # The default states are those that are shown if no option is given parser.add_argument( '-u', '--only-for-user', type=str, metavar='EMAIL', dest='user_email', help="Disable a computer only for the given user. " "If not specified, disables the computer " "globally.", ) parser.add_argument('computer', type=str, help="The name of the computer that you " "want to disable") parsed_args = parser.parse_args(args) user_email = parsed_args.user_email computername = parsed_args.computer try: computer = self.get_computer(name=computername) except NotExistent: print >> sys.stderr, "No computer exists with name '{}'".format( computername) sys.exit(1) if user_email is None: if not computer.is_enabled(): print "Computer '{}' already disabled.".format(computername) else: computer.set_enabled_state(False) print "Computer '{}' disabled.".format(computername) else: user_list = User.search_for_users(email=user_email) if user_list is None or len(user_list) == 0: print >> sys.stderr, ("No user with email '{}' in the " "database.".format(user_email)) sys.exit(1) user = user_list[0] try: dbauthinfo = computer.get_dbauthinfo(user) if dbauthinfo.enabled: dbauthinfo.enabled = False dbauthinfo.save() print "Computer '{}' disabled for user {}.".format( computername, user.get_full_name()) else: print("Computer '{}' was already disabled for user {} {}.". format(computername, user.first_name, user.last_name)) except NotExistent: print >> sys.stderr, ("User with email '{}' is not configured " "for computer '{}' yet.".format( user_email, computername))
def computer_test(self, *args): """ Test the connection to a computer. It tries to connect, to get the list of calculations on the queue and to perform other tests. """ import argparse import traceback if not is_dbenv_loaded(): load_dbenv() from django.core.exceptions import ObjectDoesNotExist from aiida.common.exceptions import NotExistent from aiida.orm.user import User from aiida.backends.utils import get_automatic_user from aiida.orm.computer import Computer as OrmComputer parser = argparse.ArgumentParser(prog=self.get_full_command_name(), description='Test a remote computer') # The default states are those that are shown if no option is given parser.add_argument( '-u', '--user', type=str, metavar='EMAIL', dest='user_email', help="Test the connection for a given AiiDA user." "If not specified, uses the current " "default user.", ) parser.add_argument( '-t', '--traceback', action='store_true', help="Print the full traceback in case an exception " "is raised", ) parser.add_argument('computer', type=str, help="The name of the computer that you " "want to test") parsed_args = parser.parse_args(args) user_email = parsed_args.user_email computername = parsed_args.computer print_traceback = parsed_args.traceback try: computer = self.get_computer(name=computername) except NotExistent: print >> sys.stderr, "No computer exists with name '{}'".format( computername) sys.exit(1) if user_email is None: user = User(dbuser=get_automatic_user()) else: user_list = User.search_for_users(email=user_email) # If no user is found if not user_list: print >> sys.stderr, ("No user with email '{}' in the " "database.".format(user_email)) sys.exit(1) user = user_list[0] print "Testing computer '{}' for user {}...".format( computername, user.email) try: dbauthinfo = computer.get_dbauthinfo(user._dbuser) except NotExistent: print >> sys.stderr, ("User with email '{}' is not yet configured " "for computer '{}' yet.".format( user.email, computername)) sys.exit(1) warning_string = None if not dbauthinfo.enabled: warning_string = ( "** NOTE! Computer is disabled for the " "specified user!\n Do you really want to test it? [y/N] ") if not computer.is_enabled(): warning_string = ("** NOTE! Computer is disabled!\n" " Do you really want to test it? [y/N] ") if warning_string: answer = raw_input(warning_string) if not (answer == 'y' or answer == 'Y'): sys.exit(0) s = OrmComputer(dbcomputer=dbauthinfo.dbcomputer).get_scheduler() t = dbauthinfo.get_transport() ## STARTING TESTS HERE num_failures = 0 num_tests = 0 try: print "> Testing connection..." with t: s.set_transport(t) num_tests += 1 for test in [ self._computer_test_get_jobs, self._computer_create_temp_file ]: num_tests += 1 try: succeeded = test(transport=t, scheduler=s, dbauthinfo=dbauthinfo) except Exception as e: print "* The test raised an exception!" if print_traceback: print "** Full traceback:" # Indent print "\n".join([ " {}".format(l) for l in traceback.format_exc().splitlines() ]) else: print "** {}: {}".format(e.__class__.__name__, e.message) print( "** (use the --traceback option to see the " "full traceback)") succeeded = False if not succeeded: num_failures += 1 if num_failures: print "Some tests failed! ({} out of {} failed)".format( num_failures, num_tests) else: print "Test completed (all {} tests succeeded)".format( num_tests) except Exception as e: print "** Error while trying to connect to the computer! I cannot " print " perform following tests, so I stop." if print_traceback: print "** Full traceback:" # Indent print "\n".join([ " {}".format(l) for l in traceback.format_exc().splitlines() ]) else: print "{}: {}".format(e.__class__.__name__, e.message) print( "(use the --traceback option to see the " "full traceback)") succeeded = False
def setup(profile, only_config, non_interactive=False, **kwargs): ''' setup an aiida profile and aiida user (and the aiida default user). :param profile: Profile name :param only_config: do not create a new user :param non_interactive: do not prompt for configuration values, fail if not all values are given as kwargs. :param backend: one of 'django', 'sqlalchemy' :param email: valid email address for the user :param db_host: hostname for the database :param db_port: port to connect to the database :param db_user: name of the db user :param db_pass: password of the db user ''' from aiida.common.setup import (create_base_dirs, create_configuration, set_default_profile, DEFAULT_UMASK, create_config_noninteractive) from aiida.backends.profile import BACKEND_SQLA, BACKEND_DJANGO from aiida.backends.utils import set_backend_type from aiida.common.exceptions import InvalidOperation # ~ cmdline_args = list(args) # ~ only_user_config = False # ~ try: # ~ cmdline_args.remove('--only-config') # ~ only_user_config = True # ~ except ValueError: # ~ # Parameter not provided # ~ pass only_user_config = only_config # ~ if cmdline_args: # ~ print >> sys.stderr, "Unknown parameters on the command line: " # ~ print >> sys.stderr, ", ".join(cmdline_args) # ~ sys.exit(1) # create the directories to store the configuration files create_base_dirs() # gprofile = 'default' if profile is None else profile # ~ gprofile = profile if settings_profile.AIIDADB_PROFILE is None \ # ~ else settings_profile.AIIDADB_PROFILE if settings_profile.AIIDADB_PROFILE and profile: sys.exit( 'the profile argument cannot be used if verdi is called with -p option: {} and {}' .format(settings_profile.AIIDADB_PROFILE, profile)) gprofile = settings_profile.AIIDADB_PROFILE or profile if gprofile == profile: settings_profile.AIIDADB_PROFILE = profile if not settings_profile.AIIDADB_PROFILE: settings_profile.AIIDADB_PROFILE = 'default' # used internally later gprofile = settings_profile.AIIDADB_PROFILE created_conf = None # ask and store the configuration of the DB if non_interactive: try: created_conf = create_config_noninteractive( profile=gprofile, backend=kwargs['backend'], email=kwargs['email'], db_host=kwargs['db_host'], db_port=kwargs['db_port'], db_name=kwargs['db_name'], db_user=kwargs['db_user'], db_pass=kwargs.get('db_pass', ''), repo=kwargs['repo'], force_overwrite=kwargs.get('force_overwrite', False)) except ValueError as e: click.echo("Error during configuation: {}".format(e.message), err=True) sys.exit(1) except KeyError as e: click.echo( "--non-interactive requires all values to be given on the commandline! Missing argument: {}" .format(e.message), err=True) sys.exit(1) else: try: created_conf = create_configuration(profile=gprofile) except ValueError as e: print >> sys.stderr, "Error during configuration: {}".format( e.message) sys.exit(1) # set default DB profiles set_default_profile('verdi', gprofile, force_rewrite=False) set_default_profile('daemon', gprofile, force_rewrite=False) if only_user_config: print( "Only user configuration requested, " "skipping the migrate command") else: print "Executing now a migrate command..." backend_choice = created_conf['AIIDADB_BACKEND'] if backend_choice == BACKEND_DJANGO: print("...for Django backend") # The correct profile is selected within load_dbenv. # Setting os.umask here since sqlite database gets created in # this step. old_umask = os.umask(DEFAULT_UMASK) # This check should be done more properly # try: # backend_type = get_backend_type() # except KeyError: # backend_type = None # # if backend_type is not None and backend_type != BACKEND_DJANGO: # raise InvalidOperation("An already existing database found" # "and a different than the selected" # "backend was used for its " # "management.") try: pass_to_django_manage([execname, 'migrate'], profile=gprofile) finally: os.umask(old_umask) set_backend_type(BACKEND_DJANGO) elif backend_choice == BACKEND_SQLA: print("...for SQLAlchemy backend") from aiida import is_dbenv_loaded from aiida.backends import settings from aiida.backends.sqlalchemy.utils import ( _load_dbenv_noschemacheck, check_schema_version) from aiida.backends.profile import load_profile # We avoid calling load_dbenv since we want to force the schema # migration if not is_dbenv_loaded(): settings.LOAD_DBENV_CALLED = True # This is going to set global variables in settings, including # settings.BACKEND load_profile() _load_dbenv_noschemacheck() # Perform the needed migration quietly check_schema_version(force_migration=True) set_backend_type(BACKEND_SQLA) else: raise InvalidOperation("Not supported backend selected.") print "Database was created successfully" # I create here the default user print "Loading new environment..." if only_user_config: from aiida.backends.utils import load_dbenv, is_dbenv_loaded # db environment has not been loaded in this case if not is_dbenv_loaded(): load_dbenv() from aiida.common.setup import DEFAULT_AIIDA_USER from aiida.orm.user import User as AiiDAUser if not AiiDAUser.search_for_users(email=DEFAULT_AIIDA_USER): print "Installing default AiiDA user..." nuser = AiiDAUser(email=DEFAULT_AIIDA_USER) nuser.first_name = "AiiDA" nuser.last_name = "Daemon" nuser.is_staff = True nuser.is_active = True nuser.is_superuser = True nuser.force_save() from aiida.common.utils import get_configured_user_email email = get_configured_user_email() print "Starting user configuration for {}...".format(email) if email == DEFAULT_AIIDA_USER: print "You set up AiiDA using the default Daemon email ({}),".format( email) print "therefore no further user configuration will be asked." else: # Ask to configure the new user if not non_interactive: user.configure.main(args=[email]) else: # or don't ask aiida.cmdline.commands.user.do_configure( email=kwargs['email'], first_name=kwargs.get('first_name'), last_name=kwargs.get('last_name'), institution=kwargs.get('institution'), no_password=True, non_interactive=non_interactive, force=True) print "Setup finished."
def get_bands_and_parents_structure(self, args): """ Search for bands and return bands and the closest structure that is a parent of the instance. This is the backend independent way, can be overriden for performance reason :returns: A list of sublists, each latter containing (in order): pk as string, formula as string, creation date, bandsdata-label """ import datetime from aiida.utils import timezone from aiida.orm.querybuilder import QueryBuilder from aiida.backends.utils import get_automatic_user from aiida.orm.implementation import User from aiida.orm.implementation import Group from aiida.orm.data.structure import (get_formula, get_symbols_string) from aiida.orm.data.array.bands import BandsData from aiida.orm.data.structure import StructureData qb = QueryBuilder() if args.all_users is False: au = get_automatic_user() user = User(dbuser=au) qb.append(User, tag="creator", filters={"email": user.email}) else: qb.append(User, tag="creator") bdata_filters = {} if args.past_days is not None: now = timezone.now() n_days_ago = now - datetime.timedelta(days=args.past_days) bdata_filters.update({"ctime": {'>=': n_days_ago}}) qb.append(BandsData, tag="bdata", created_by="creator", filters=bdata_filters, project=["id", "label", "ctime"]) group_filters = {} if args.group_name is not None: group_filters.update({"name": {"in": args.group_name}}) if args.group_pk is not None: group_filters.update({"id": {"in": args.group_pk}}) if group_filters: qb.append(Group, tag="group", filters=group_filters, group_of="bdata") qb.append( StructureData, tag="sdata", ancestor_of="bdata", # We don't care about the creator of StructureData project=["id", "attributes.kinds", "attributes.sites"]) qb.order_by({StructureData: {'ctime': 'desc'}}) list_data = qb.distinct() entry_list = [] already_visited_bdata = set() for [bid, blabel, bdate, sid, akinds, asites] in list_data.all(): # We process only one StructureData per BandsData. # We want to process the closest StructureData to # every BandsData. # We hope that the StructureData with the latest # creation time is the closest one. # This will be updated when the QueryBuilder supports # order_by by the distance of two nodes. if already_visited_bdata.__contains__(bid): continue already_visited_bdata.add(bid) if args.element is not None: all_symbols = [_["symbols"][0] for _ in akinds] if not any([s in args.element for s in all_symbols]): continue if args.element_only is not None: all_symbols = [_["symbols"][0] for _ in akinds] if not all([s in all_symbols for s in args.element_only]): continue # We want only the StructureData that have attributes if akinds is None or asites is None: continue symbol_dict = {} for k in akinds: symbols = k['symbols'] weights = k['weights'] symbol_dict[k['name']] = get_symbols_string(symbols, weights) try: symbol_list = [] for s in asites: symbol_list.append(symbol_dict[s['kind_name']]) formula = get_formula(symbol_list, mode=args.formulamode) # If for some reason there is no kind with the name # referenced by the site except KeyError: formula = "<<UNKNOWN>>" entry_list.append( [str(bid), str(formula), bdate.strftime('%d %b %Y'), blabel]) return entry_list
def code_list(self, *args): """ List available codes """ import argparse parser = argparse.ArgumentParser( prog=self.get_full_command_name(), description='List the codes in the database.') # The default states are those that are shown if no option is given parser.add_argument( '-c', '--computer', help="Filter only codes on a given computer", ) parser.add_argument( '-p', '--plugin', help="Filter only calculation with a given plugin", ) parser.add_argument( '-A', '--all-users', dest='all_users', action='store_true', help="Show codes of all users", ) parser.add_argument( '-o', '--show-owner', dest='show_owner', action='store_true', help="Show also the owner of the code", ) parser.add_argument( '-a', '--all-codes', action='store_true', help="Show also hidden codes", ) parser.set_defaults(all_users=False, hidden=False) parsed_args = parser.parse_args(args) computer_filter = parsed_args.computer plugin_filter = parsed_args.plugin all_users = parsed_args.all_users show_owner = parsed_args.show_owner reveal_filter = parsed_args.all_codes from aiida.orm.querybuilder import QueryBuilder from aiida.orm.code import Code from aiida.orm.computer import Computer from aiida.orm.user import User from aiida.backends.utils import get_automatic_user qb_user_filters = dict() if not all_users: user = User(dbuser=get_automatic_user()) qb_user_filters['email'] = user.email qb_computer_filters = dict() if computer_filter is not None: qb_computer_filters['name'] = computer_filter qb_code_filters = dict() if plugin_filter is not None: qb_code_filters['attributes.input_plugin'] = plugin_filter if not reveal_filter: qb_code_filters['attributes.hidden'] = {"~==": True} qb = QueryBuilder() qb.append(Code, tag="code", filters=qb_code_filters, project=["id", "label"]) qb.append(Computer, computer_of="code", project=["name"], filters=qb_computer_filters) qb.append(User, creator_of="code", project=["email"], filters=qb_user_filters) print "# List of configured codes:" print "# (use 'verdi code show CODEID' to see the details)" if qb.count > 0: for pk, label, computername, useremail in qb.iterall(): if show_owner: owner_string = " ({})".format(useremail) else: owner_string = "" if computername is None: computernamestring = "" else: computernamestring = "@{}".format(computername) print "* pk {} - {}{}{}".format(pk, label, computernamestring, owner_string) else: print "# No codes found matching the specified criteria."
def code_list(self, *args): """ List available codes """ import argparse parser = argparse.ArgumentParser( prog=self.get_full_command_name(), description='List the codes in the database.') # The default states are those that are shown if no option is given parser.add_argument( '-c', '--computer', help="Filter only codes on a given computer", ) parser.add_argument( '-p', '--plugin', help="Filter only calculation with a given plugin", ) parser.add_argument( '-A', '--all-users', dest='all_users', action='store_true', help="Show codes of all users", ) parser.add_argument( '-o', '--show-owner', dest='show_owner', action='store_true', help="Show also the owner of the code", ) parser.add_argument( '-a', '--all-codes', action='store_true', help="Show also hidden codes", ) parser.set_defaults(all_users=False, hidden=False) parsed_args = parser.parse_args(args) computer_filter = parsed_args.computer plugin_filter = parsed_args.plugin all_users = parsed_args.all_users show_owner = parsed_args.show_owner reveal_filter = parsed_args.all_codes from aiida.orm.querybuilder import QueryBuilder from aiida.orm.code import Code from aiida.orm.computer import Computer from aiida.orm.user import User from aiida.backends.utils import get_automatic_user qb_user_filters = dict() if not all_users: user = User(dbuser=get_automatic_user()) qb_user_filters['email'] = user.email qb_computer_filters = dict() if computer_filter is not None: qb_computer_filters['name'] = computer_filter qb_code_filters = dict() if plugin_filter is not None: qb_code_filters['attributes.input_plugin'] = plugin_filter if not reveal_filter: qb_code_filters['attributes.hidden'] = {"~==": True} print "# List of configured codes:" print "# (use 'verdi code show CODEID' to see the details)" if computer_filter is not None: qb = QueryBuilder() qb.append(Code, tag="code", filters=qb_code_filters, project=["id", "label"]) # We have a user assigned to the code so we can ask for the # presence of a user even if there is no user filter qb.append(User, creator_of="code", project=["email"], filters=qb_user_filters) # We also add the filter on computer. This will automatically # return codes that have a computer (and of course satisfy the # other filters). The codes that have a computer attached are the # remote codes. qb.append(Computer, computer_of="code", project=["name"], filters=qb_computer_filters) self.print_list_res(qb, show_owner) # If there is no filter on computers else: # Print all codes that have a computer assigned to them # (these are the remote codes) qb = QueryBuilder() qb.append(Code, tag="code", filters=qb_code_filters, project=["id", "label"]) # We have a user assigned to the code so we can ask for the # presence of a user even if there is no user filter qb.append(User, creator_of="code", project=["email"], filters=qb_user_filters) qb.append(Computer, computer_of="code", project=["name"]) self.print_list_res(qb, show_owner) # Now print all the local codes. To get the local codes we ask # the dbcomputer_id variable to be None. qb = QueryBuilder() comp_non_existence = {"dbcomputer_id": {"==": None}} if not qb_code_filters: qb_code_filters = comp_non_existence else: new_qb_code_filters = { "and": [qb_code_filters, comp_non_existence] } qb_code_filters = new_qb_code_filters qb.append(Code, tag="code", filters=qb_code_filters, project=["id", "label"]) # We have a user assigned to the code so we can ask for the # presence of a user even if there is no user filter qb.append(User, creator_of="code", project=["email"], filters=qb_user_filters) self.print_list_res(qb, show_owner)
def test_configure_from_file(configure): from aiida.orm.user import User user = User.get_all_users()[0] assert user.first_name == 'AiiDA'
def test_6(self): """ This test checks that nodes belonging to user A (which is not the default user) can be correctly exported, imported, enriched with nodes from the default user, re-exported & re-imported and that in the end all the nodes that have been finally imported belonging to the right users. """ import os import shutil import tempfile from aiida.orm import load_node from aiida.orm.calculation.job import JobCalculation from aiida.orm.data.structure import StructureData from aiida.orm.importexport import export from aiida.common.datastructures import calc_states from aiida.common.links import LinkType from aiida.common.utils import get_configured_user_email from aiida.orm.user import User # Creating a folder for the import/export files temp_folder = tempfile.mkdtemp() try: # Create another user new_email = "[email protected]" user = User(email=new_email) user.force_save() # Create a structure data node that has a calculation as output sd1 = StructureData() sd1.dbnode.user = user._dbuser sd1.label = 'sd1' sd1.store() jc1 = JobCalculation() jc1.set_computer(self.computer) jc1.set_resources({"num_machines": 1, "num_mpiprocs_per_machine": 1}) jc1.dbnode.user = user._dbuser jc1.label = 'jc1' jc1.store() jc1.add_link_from(sd1) jc1._set_state(calc_states.PARSING) # Create some nodes from a different user sd2 = StructureData() sd2.dbnode.user = user._dbuser sd2.label = 'sd2' sd2.store() sd2.add_link_from(jc1, label='l1', link_type=LinkType.RETURN) # Set the jc1 to FINISHED jc1._set_state(calc_states.FINISHED) # At this point we export the generated data filename1 = os.path.join(temp_folder, "export1.tar.gz") export([sd2.dbnode], outfile=filename1, silent=True) uuids1 = [sd1.uuid, jc1.uuid, sd2.uuid] self.clean_db() self.insert_data() import_data(filename1, silent=True) # Check that the imported nodes are correctly imported and that # the user assigned to the nodes is the right one for uuid in uuids1: self.assertEquals(load_node(uuid).get_user().email, new_email) # Now we continue to generate more data based on the imported # data sd2_imp = load_node(sd2.uuid) jc2 = JobCalculation() jc2.set_computer(self.computer) jc2.set_resources({"num_machines": 1, "num_mpiprocs_per_machine": 1}) jc2.label = 'jc2' jc2.store() jc2.add_link_from(sd2_imp, label='l2') jc2._set_state(calc_states.PARSING) sd3 = StructureData() sd3.label = 'sd3' sd3.store() sd3.add_link_from(jc2, label='l3', link_type=LinkType.RETURN) # Set the jc2 to FINISHED jc2._set_state(calc_states.FINISHED) # Store the UUIDs of the nodes that should be checked # if they can be imported correctly. uuids2 = [jc2.uuid, sd3.uuid] filename2 = os.path.join(temp_folder, "export2.tar.gz") export([sd3.dbnode], outfile=filename2, silent=True) self.clean_db() self.insert_data() import_data(filename2, silent=True) # Check that the imported nodes are correctly imported and that # the user assigned to the nodes is the right one for uuid in uuids1: self.assertEquals(load_node(uuid).get_user().email, new_email) for uuid in uuids2: self.assertEquals(load_node(uuid).get_user().email, get_configured_user_email()) finally: # Deleting the created temporary folder shutil.rmtree(temp_folder, ignore_errors=True)
def test_5(self): """ This test checks that nodes belonging to different users are correctly exported & imported. """ import os import shutil import tempfile from aiida.orm import load_node from aiida.orm.calculation.job import JobCalculation from aiida.orm.data.structure import StructureData from aiida.orm.importexport import export from aiida.common.datastructures import calc_states from aiida.common.links import LinkType from aiida.orm.user import User from aiida.common.utils import get_configured_user_email # Creating a folder for the import/export files temp_folder = tempfile.mkdtemp() try: # Create another user new_email = "[email protected]" user = User(email=new_email) user.force_save() # Create a structure data node that has a calculation as output sd1 = StructureData() sd1.dbnode.user = user._dbuser sd1.label = 'sd1' sd1.store() jc1 = JobCalculation() jc1.set_computer(self.computer) jc1.set_resources({"num_machines": 1, "num_mpiprocs_per_machine": 1}) jc1.dbnode.user = user._dbuser jc1.label = 'jc1' jc1.store() jc1.add_link_from(sd1) jc1._set_state(calc_states.PARSING) # Create some nodes from a different user sd2 = StructureData() sd2.dbnode.user = user._dbuser sd2.label = 'sd2' sd2.store() sd2.add_link_from(jc1, label='l1', link_type=LinkType.RETURN) jc2 = JobCalculation() jc2.set_computer(self.computer) jc2.set_resources({"num_machines": 1, "num_mpiprocs_per_machine": 1}) jc2.label = 'jc2' jc2.store() jc2.add_link_from(sd2, label='l2') jc2._set_state(calc_states.PARSING) sd3 = StructureData() sd3.label = 'sd3' sd3.store() sd3.add_link_from(jc2, label='l3', link_type=LinkType.RETURN) uuids_u1 = [sd1.uuid, jc1.uuid, sd2.uuid] uuids_u2 = [jc2.uuid, sd3.uuid] filename = os.path.join(temp_folder, "export.tar.gz") export([sd3.dbnode], outfile=filename, silent=True) self.clean_db() import_data(filename, silent=True) # Check that the imported nodes are correctly imported and that # the user assigned to the nodes is the right one for uuid in uuids_u1: self.assertEquals(load_node(uuid).get_user().email, new_email) for uuid in uuids_u2: self.assertEquals(load_node(uuid).get_user().email, get_configured_user_email()) finally: # Deleting the created temporary folder shutil.rmtree(temp_folder, ignore_errors=True)
def configure_user(self, *args): """ Configure the user that can run the daemon. """ if not is_dbenv_loaded(): from aiida.backends.utils import load_dbenv load_dbenv(process='daemon') if args: print >> sys.stderr, ( "No arguments allowed for the '{}' command.".format( self.get_full_command_name())) sys.exit(1) from aiida.utils import timezone from aiida.backends.utils import get_daemon_user, set_daemon_user from aiida.common.utils import (get_configured_user_email, query_yes_no, query_string) from aiida.daemon.timestamps import get_most_recent_daemon_timestamp from aiida.common.utils import str_timedelta from aiida.orm.user import User old_daemon_user = get_daemon_user() this_user = get_configured_user_email() print("> Current default user: {}".format(this_user)) print("> Currently configured user who can run the daemon: {}".format( old_daemon_user)) if old_daemon_user == this_user: print( " (therefore, at the moment you are the user who can run " "the daemon)") pid = self.get_daemon_pid() if pid is not None: print("The daemon is running! I will not proceed.") sys.exit(1) else: print(" (therefore, you cannot run the daemon, at the moment)") most_recent_timestamp = get_most_recent_daemon_timestamp() print "*" * 76 print "* {:72s} *".format("WARNING! Change this setting only if you " "are sure of what you are doing.") print "* {:72s} *".format("Moreover, make sure that the " "daemon is stopped.") if most_recent_timestamp is not None: timestamp_delta = timezone.now() - most_recent_timestamp last_check_string = ( "[The most recent timestamp from the daemon was {}]".format( str_timedelta(timestamp_delta))) print "* {:72s} *".format(last_check_string) print "*" * 76 answer = query_yes_no( "Are you really sure that you want to change " "the daemon user?", default="no") if not answer: sys.exit(0) print "" print "Enter below the email of the new user who can run the daemon." new_daemon_user_email = query_string("New daemon user: "******"ERROR! The user you specified ({}) does " "not exist in the database!!".format(new_daemon_user_email)) print("The available users are {}".format( [_.email for _ in User.search_for_users()])) sys.exit(1) set_daemon_user(new_daemon_user_email) print "The new user that can run the daemon is now {} {}.".format( found_users[0].first_name, found_users[0].last_name)
def get_aiida_class(self): from aiida.orm.user import User return User(dbuser=self)