X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Fmanagers%2Fregistry_manager.py;h=93d2ea8ff760374b71978901e9f25313edc095af;hb=cf630d87d633f3861e3ac8a50433fa29ca46a74e;hp=6e1026c2dafaa2404a85f5331e935988e052411c;hpb=572cfc8f48dab8398a51f29eeaaaf007be12be54;p=sfa.git diff --git a/sfa/managers/registry_manager.py b/sfa/managers/registry_manager.py index 6e1026c2..93d2ea8f 100644 --- a/sfa/managers/registry_manager.py +++ b/sfa/managers/registry_manager.py @@ -8,8 +8,6 @@ import commands from sfa.util.faults import RecordNotFound, AccountNotEnabled, PermissionError, MissingAuthority, \ UnknownSfaType, ExistingRecord, NonExistingRecord from sfa.util.prefixTree import prefixTree -from sfa.util.record import SfaRecord -from sfa.util.table import SfaTable from sfa.util.xrn import Xrn, get_authority, hrn_to_urn, urn_to_hrn from sfa.util.plxrn import hrn_to_pl_login_base from sfa.util.version import version_core @@ -20,6 +18,9 @@ from sfa.trust.credential import Credential from sfa.trust.certificate import Certificate, Keypair, convert_public_key from sfa.trust.gid import create_uuid +from sfa.storage.record import SfaRecord +from sfa.storage.table import SfaTable + class RegistryManager: def __init__ (self): pass @@ -55,7 +56,8 @@ class RegistryManager: # verify_cancreate_credential requires that the member lists # (researchers, pis, etc) be filled in - if not self.driver.is_enabled_entity (record, api.aggregates): + self.driver.augment_records_with_testbed_info (record) + if not self.driver.is_enabled (record): raise AccountNotEnabled(": PlanetLab account %s is not enabled. Please contact your site PI" %(record['email'])) # get the callers gid @@ -137,9 +139,23 @@ class RegistryManager: # table = SfaTable() local_records = table.findObjects({'hrn': local_hrns}) - # xxx driver todo + if full: - self.driver.fill_record_info(local_records, api.aggregates) + # in full mode we get as much info as we can, which involves contacting the + # testbed for getting implementation details about the record + self.driver.augment_records_with_testbed_info(local_records) + # also we fill the 'url' field for known authorities + # used to be in the driver code, sounds like a poorman thing though + def solve_neighbour_url (record): + if not record['type'].startswith('authority'): return + hrn=record['hrn'] + for neighbour_dict in [ api.aggregates, api.registries ]: + if hrn in neighbour_dict: + record['url']=neighbour_dict[hrn].get_url() + return + [ solve_neighbour_url (record) for record in local_records ] + + # convert local record objects to dicts records.extend([dict(record) for record in local_records]) @@ -197,7 +213,33 @@ class RegistryManager: pkey = certificate.get_pubkey() gid = api.auth.hierarchy.create_gid(xrn, create_uuid(), pkey) return gid.save_to_string(save_parents=True) + + #################### + # utility for handling relationships among the SFA objects + # given that the SFA db does not handle this sort of relationsships + # it will rely on side-effects in the testbed to keep this persistent + + # subject_record describes the subject of the relationships + # ref_record contains the target values for the various relationships we need to manage + # (to begin with, this is just the slice x person relationship) + def update_relations (self, subject_record, ref_record): + type=subject_record['type'] + if type=='slice': + self.update_relation(subject_record, 'researcher', ref_record.get('researcher'), 'user') + # field_key is the name of one field in the record, typically 'researcher' for a 'slice' record + # hrns is the list of hrns that should be linked to the subject from now on + # target_type would be e.g. 'user' in the 'slice' x 'researcher' example + def update_relation (self, sfa_record, field_key, hrns, target_type): + # locate the linked objects in our db + subject_type=sfa_record['type'] + subject_id=sfa_record['pointer'] + table = SfaTable() + link_sfa_records = table.find ({'type':target_type, 'hrn': hrns}) + link_ids = [ rec.get('pointer') for rec in link_sfa_records ] + self.driver.update_relation (subject_type, target_type, subject_id, link_ids) + + def Register(self, api, record): hrn, type = record['hrn'], record['type'] @@ -220,12 +262,11 @@ class RegistryManager: if 'gid' not in record: uuid = create_uuid() pkey = Keypair(create=True) - if 'key' in record and record['key']: + if 'keys' in record and record['keys']: + pub_key=record['keys'] # use only first key in record - if isinstance(record['key'], types.ListType): - pub_key = record['key'][0] - else: - pub_key = record['key'] + if isinstance(record['keys'], types.ListType): + pub_key = record['keys'][0] pkey = convert_public_key(pub_key) gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey) @@ -244,15 +285,15 @@ class RegistryManager: # update testbed-specific data f needed logger.info("Getting driver from manager=%s"%self) - pointer = self.driver.register (hrn, record, pub_key) + pointer = self.driver.register (record, hrn, pub_key) record.set_pointer(pointer) record_id = table.insert(record) record['record_id'] = record_id # update membership for researchers, pis, owners, operators - self.driver.update_membership(None, record) - + self.update_relations (record, record) + return record.get_gid_object().save_to_string(save_parents=True) def Update(self, api, record_dict): @@ -268,75 +309,39 @@ class RegistryManager: record = records[0] record['last_updated'] = time.gmtime() - # Update_membership needs the membership lists in the existing record - # filled in, so it can see if members were added or removed - self.driver.fill_record_info(record, api.aggregates) - + # 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'] - # update the PLC information that was specified with the record - - if (type == "authority"): - self.driver.UpdateSite(pointer, new_record) - - elif type == "slice": - pl_record=self.driver.sfa_fields_to_pl_fields(type, hrn, new_record) - if 'name' in pl_record: - pl_record.pop('name') - self.driver.UpdateSlice(pointer, pl_record) - - elif type == "user": - # SMBAKER: UpdatePerson only allows a limited set of fields to be - # updated. Ideally we should have a more generic way of doing - # this. I copied the field names from UpdatePerson.py... - update_fields = {} - all_fields = new_record - for key in all_fields.keys(): - if key in ['first_name', 'last_name', 'title', 'email', - 'password', 'phone', 'url', 'bio', 'accepted_aup', - 'enabled']: - update_fields[key] = all_fields[key] - self.driver.UpdatePerson(pointer, update_fields) - - if 'key' in new_record and new_record['key']: - # must check this key against the previous one if it exists - persons = self.driver.GetPersons([pointer], ['key_ids']) - person = persons[0] - keys = person['key_ids'] - keys = self.driver.GetKeys(person['key_ids']) - key_exists = False - if isinstance(new_record['key'], types.ListType): - new_key = new_record['key'][0] - else: - new_key = new_record['key'] - - # Delete all stale keys - for key in keys: - if new_record['key'] != key['key']: - self.driver.DeleteKey(key['key_id']) - else: - key_exists = True - if not key_exists: - self.driver.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key}) - - # update the openssl key and gid - pkey = convert_public_key(new_key) - uuid = create_uuid() - gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey) - gid = gid_object.save_to_string(save_parents=True) - record['gid'] = gid - record = SfaRecord(dict=record) - table.update(record) - - elif type == "node": - self.driver.UpdateNode(pointer, new_record) - else: - raise UnknownSfaType(type) + # is the a change in keys ? + new_key=None + if type=='user': + if 'keys' in new_record and new_record['keys']: + new_key=new_record['keys'] + 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, new_record, hrn, new_key): + logger.warning("driver.update failed") + # take new_key into account + if new_key: + # update the openssl key and gid + pkey = convert_public_key(new_key) + uuid = create_uuid() + gid_object = api.auth.hierarchy.create_gid(urn, uuid, pkey) + gid = gid_object.save_to_string(save_parents=True) + record['gid'] = gid + record = SfaRecord(dict=record) + table.update(record) + # update membership for researchers, pis, owners, operators - self.driver.update_membership(record, new_record) + self.update_relations (record, new_record) return 1 @@ -355,7 +360,7 @@ class RegistryManager: record = records[0] type = record['type'] - if not type in ['slice', 'user', 'node', 'authority'] : + if type not in ['slice', 'user', 'node', 'authority'] : raise UnknownSfaType(type) credential = api.getCredential() @@ -370,8 +375,12 @@ class RegistryManager: result=registries[registry].remove_peer_object(credential, record, origin_hrn) except: pass + # call testbed callback first - self.driver.remove(record) + # IIUC this is done on the local testbed TOO because of the refreshpeer link + if not self.driver.remove(record): + logger.warning("driver.remove failed") + # delete from sfa db table.remove(record)