From 2a47b9c79b0a6996f61eb70606be88f54cc4a398 Mon Sep 17 00:00:00 2001 From: Thierry Parmentelat Date: Fri, 11 May 2012 18:54:22 +0200 Subject: [PATCH] review management of relationships - allow to update them with sfaadmin --- sfa/client/sfaadmin.py | 36 +++++++++++++++-------- sfa/managers/registry_manager.py | 49 +++++++++++++++++--------------- sfa/plc/pldriver.py | 7 ++++- sfa/storage/model.py | 20 +++++++++++++ 4 files changed, 76 insertions(+), 36 deletions(-) diff --git a/sfa/client/sfaadmin.py b/sfa/client/sfaadmin.py index 75bd3370..54db87a4 100755 --- a/sfa/client/sfaadmin.py +++ b/sfa/client/sfaadmin.py @@ -70,8 +70,10 @@ class RegistryCommands(Commands): save_records_to_file(outfile, records) - def _record_dict(self, xrn=None, type=None, url=None, key=None, \ - description=None, slices='', researchers=''): + def _record_dict(self, xrn=None, type=None, + url=None, description=None, email='', + key=None, + slices=[], researchers=[], pis=[]): record_dict = {} if xrn: if type: @@ -83,6 +85,8 @@ class RegistryCommands(Commands): record_dict['type'] = xrn.get_type() if url: record_dict['url'] = url + if description: + record_dict['description'] = description if key: try: pubkey = open(key, 'r').read() @@ -92,16 +96,21 @@ class RegistryCommands(Commands): if slices: record_dict['slices'] = slices if researchers: - record_dict['researchers'] = researchers - if description: - record_dict['description'] = description + record_dict['researcher'] = researchers + if email: + record_dict['email'] = email + if pis: + record_dict['pi'] = pis return record_dict @args('-x', '--xrn', dest='xrn', metavar='', help='object hrn/urn (mandatory)') @args('-t', '--type', dest='type', metavar='', help='object type', default=None) - @args('-u', '--url', dest='url', metavar='', help='URL', default=None) + @args('-e', '--email', dest='email', default="", + help="email (mandatory for users)") + @args('-u', '--url', dest='url', metavar='', default=None, + help="URL, useful for slices") @args('-d', '--description', dest='description', metavar='', - help='Description', default=None) + help='Description, useful for slices', default=None) @args('-k', '--key', dest='key', metavar='', help='public key string or file', default=None) @args('-s', '--slices', dest='slices', metavar='', help='slice xrns', @@ -112,10 +121,10 @@ class RegistryCommands(Commands): help='Principal Investigators/Project Managers ', default='', type="str", action='callback', callback=optparse_listvalue_callback) def register(self, xrn, type=None, url=None, description=None, key=None, slices='', - pis='', researchers=''): - """Create a new Registry recory""" + pis='', researchers='',email=''): + """Create a new Registry record""" record_dict = self._record_dict(xrn=xrn, type=type, url=url, key=key, - slices=slices, researchers=researchers) + slices=slices, researchers=researchers, email=email, pis=pis) self.api.manager.Register(self.api, record_dict) @@ -137,7 +146,8 @@ class RegistryCommands(Commands): pis='', researchers=''): """Update an existing Registry record""" record_dict = self._record_dict(xrn=xrn, type=type, url=url, description=description, - key=key, slices=slices, researchers=researchers) + key=key, slices=slices, researchers=researchers, pis=pis) + for (k,v) in record_dict.items(): print k,'=',v self.api.manager.Update(self.api, record_dict) @args('-x', '--xrn', dest='xrn', metavar='', help='object hrn/urn (mandatory)') @@ -420,11 +430,13 @@ class SfaAdmin: # execute command try: - # print "invoking %s *=%s **=%s"%(command.__name__,cmd_args, cmd_kwds) + #print "invoking %s *=%s **=%s"%(command.__name__,cmd_args, cmd_kwds) command(*cmd_args, **cmd_kwds) sys.exit(0) except TypeError: print "Possible wrong number of arguments supplied" + #import traceback + #traceback.print_exc() print command.__doc__ parser.print_help() #raise diff --git a/sfa/managers/registry_manager.py b/sfa/managers/registry_manager.py index 51b2be0d..5cc0ca85 100644 --- a/sfa/managers/registry_manager.py +++ b/sfa/managers/registry_manager.py @@ -314,18 +314,13 @@ class RegistryManager: gid = auth_info.get_gid_object() record.gid=gid.save_to_string(save_parents=True) - elif isinstance (record, RegSlice): # locate objects for relationships - if hasattr (record, 'researcher'): - # we get the list of researcher hrns as - researcher_hrns = record.researcher - # strip that in case we have words - researcher_hrns = [ x.strip() for x in researcher_hrns ] - logger.info ("incoming researchers %s"%researcher_hrns) - request = dbsession.query (RegUser).filter(RegUser.hrn.in_(researcher_hrns)) - logger.info ("%d incoming hrns, %d matches found"%(len(researcher_hrns),request.count())) - researchers = dbsession.query (RegUser).filter(RegUser.hrn.in_(researcher_hrns)).all() - record.reg_researchers = researchers + pi_hrns = getattr(record,'pi',None) + if pi_hrns is not None: record.update_pis (pi_hrns) + + elif isinstance (record, RegSlice): + researcher_hrns = getattr(record,'researcher',None) + if researcher_hrns is not None: record.update_researchers (researcher_hrns) elif isinstance (record, RegUser): # create RegKey objects for incoming keys @@ -347,9 +342,8 @@ class RegistryManager: def Update(self, api, record_dict): assert ('type' in record_dict) - new_record=RegRecord(dict=record_dict) - type = new_record.type - hrn = new_record.hrn + new_record=make_record(dict=record_dict) + (type,hrn) = (new_record.type, new_record.hrn) # make sure the record exists record = dbsession.query(RegRecord).filter_by(type=type,hrn=hrn).first() @@ -357,15 +351,11 @@ class RegistryManager: raise RecordNotFound("hrn=%s, type=%s"%(hrn,type)) record.just_updated() - # validate the type - if type not in ['authority', 'slice', 'node', 'user']: - raise UnknownSfaType(type) - # Use the pointer from the existing record, not the one that the user # gave us. This prevents the user from inserting a forged pointer pointer = record.pointer - # is the a change in keys ? + # is there a change in keys ? new_key=None if type=='user': if getattr(new_key,'keys',None): @@ -373,10 +363,6 @@ class RegistryManager: if isinstance (new_key,types.ListType): new_key=new_key[0] - # update the PLC information that was specified with the record - if not self.driver.update (record.__dict__, new_record.__dict__, hrn, new_key): - logger.warning("driver.update failed") - # take new_key into account if new_key: # update the openssl key and gid @@ -388,6 +374,23 @@ class RegistryManager: record.gid = gid dsession.commit() + # xxx should do side effects from new_record to record + # not too sure how to do that + # not too big a deal with planetlab as the driver is authoritative, but... + + # update native relations + if isinstance (record, RegSlice): + researcher_hrns = getattr(new_record,'researcher',None) + if researcher_hrns is not None: record.update_researchers (researcher_hrns) + + elif isinstance (record, RegAuthority): + pi_hrns = getattr(new_record,'pi',None) + if pi_hrns is not None: record.update_pis (pi_hrns) + + # update the PLC information that was specified with the record + if not self.driver.update (record.__dict__, new_record.__dict__, hrn, new_key): + logger.warning("driver.update failed") + # update membership for researchers, pis, owners, operators self.update_driver_relations (record, new_record) diff --git a/sfa/plc/pldriver.py b/sfa/plc/pldriver.py index 07273caa..49908ba8 100644 --- a/sfa/plc/pldriver.py +++ b/sfa/plc/pldriver.py @@ -540,7 +540,12 @@ class PlDriver (Driver): logger.debug ("del_target_id = %s (type=%s)"%(target_id,type(target_id))) self.shell.DeletePersonFromSlice (target_id, subject_id) elif subject_type == 'authority' and target_type == 'user' and relation_name == 'pi': - logger.log ("WARNING: XXX todo pldriver.update_relation not implemented for the 'pi' relationship") + # due to the plcapi limitations this means essentially adding pi role to all people in the list + # it's tricky to remove any pi role here, although it might be desirable + persons = self.shell.GetPersons (target_ids) + for person in persons: + if 'pi' not in person['roles']: + self.shell.AddRoleToPerson('pi',person['person_id']) else: logger.info('unexpected relation %s to maintain, %s -> %s'%(relation_name,subject_type,target_type)) diff --git a/sfa/storage/model.py b/sfa/storage/model.py index 679da91a..c187dcc5 100644 --- a/sfa/storage/model.py +++ b/sfa/storage/model.py @@ -188,6 +188,16 @@ class RegAuthority (RegRecord): def __repr__ (self): return RegRecord.__repr__(self).replace("Record","Authority") + def update_pis (self, pi_hrns): + # don't ruin the import of that file in a client world + from sfa.storage.alchemy import dbsession + # strip that in case we have words + pi_hrns = [ x.strip() for x in pi_hrns ] + request = dbsession.query (RegUser).filter(RegUser.hrn.in_(pi_hrns)) + logger.info ("RegAuthority.update_pis: %d incoming pis, %d matches found"%(len(pi_hrns),request.count())) + pis = dbsession.query (RegUser).filter(RegUser.hrn.in_(pi_hrns)).all() + self.reg_pis = pis + #################### class RegSlice (RegRecord): __tablename__ = 'slices' @@ -208,6 +218,16 @@ class RegSlice (RegRecord): def __repr__ (self): return RegRecord.__repr__(self).replace("Record","Slice") + def update_researchers (self, researcher_hrns): + # don't ruin the import of that file in a client world + from sfa.storage.alchemy import dbsession + # strip that in case we have words + researcher_hrns = [ x.strip() for x in researcher_hrns ] + request = dbsession.query (RegUser).filter(RegUser.hrn.in_(researcher_hrns)) + logger.info ("RegSlice.update_researchers: %d incoming researchers, %d matches found"%(len(researcher_hrns),request.count())) + researchers = dbsession.query (RegUser).filter(RegUser.hrn.in_(researcher_hrns)).all() + self.reg_researchers = researchers + # when dealing with credentials, we need to retrieve the PIs attached to a slice def get_pis (self): # don't ruin the import of that file in a client world -- 2.43.0