expose hrns of builtin related entities as a result of Resolve; this
Thierry Parmentelat [Thu, 20 Sep 2012 14:08:39 +0000 (16:08 +0200)]
is required now that the default value for 'details' is False, and
that we cannot rely on an underlying testbed

sfa/managers/registry_manager.py
sfa/storage/model.py
sfa/storage/record.py

index 407e779..687e1c6 100644 (file)
@@ -17,7 +17,8 @@ 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.model import make_record, RegRecord, RegAuthority, RegUser, RegSlice, RegKey
+from sfa.storage.model import make_record, RegRecord, RegAuthority, RegUser, RegSlice, RegKey, \
+    augment_with_related_hrns
 from sfa.storage.alchemy import dbsession
 
 class RegistryManager:
@@ -53,13 +54,6 @@ class RegistryManager:
         if not record:
             raise RecordNotFound("hrn=%s, type=%s"%(hrn,type))
 
-        # xxx for the record only
-        # used to call this, which was wrong, now all needed data is natively is our DB
-        # self.driver.augment_records_with_testbed_info (record.__dict__)
-        # likewise, we deprecate is_enabled which was not really useful
-        # if not self.driver.is_enabled (record.__dict__): ...
-        # xxx for the record only
-    
         # get the callers gid
         # if caller_xrn is not specified assume the caller is the record
         # object itself.
@@ -159,7 +153,11 @@ class RegistryManager:
         if type:
             local_records = local_records.filter_by(type=type)
         local_records=local_records.all()
-        logger.info("Resolve details=%s: local_records=%s (type=%s)"%(details,local_records,type))
+        
+        for local_record in local_records:
+            augment_with_related_hrns (local_record)
+
+        logger.info("Resolve, (details=%s,type=%s) local_records=%s "%(details,type,local_records))
         local_dicts = [ record.__dict__ for record in local_records ]
         
         if details:
@@ -181,7 +179,8 @@ class RegistryManager:
         # xxx somehow here calling dict(record) issues a weird error
         # however record.todict() seems to work fine
         # records.extend( [ dict(record) for record in local_records ] )
-        records.extend( [ record.todict() for record in local_records ] )    
+        records.extend( [ record.todict(exclude_type=RegRecord) for record in local_records ] )
+
         if not records:
             raise RecordNotFound(str(hrns))
     
@@ -246,12 +245,10 @@ class RegistryManager:
     
     ####################
     # 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)
+    # (to begin with, this is just the slice x person (researcher) and authority x person (pi) relationships)
     def update_driver_relations (self, subject_obj, ref_obj):
         type=subject_obj.type
         #for (k,v) in subject_obj.__dict__.items(): print k,'=',v
index 64da316..05046d0 100644 (file)
@@ -361,3 +361,27 @@ def make_record_xml (xml):
     logger.info("load from xml, keys=%s"%xml_dict.keys())
     return make_record_dict (xml_dict)
 
+####################
+# augment local records with data from builtin relationships
+# expose related objects as a list of hrns
+# we pick names that clearly won't conflict with the ones used in the old approach,
+# were the relationships data came from the testbed side
+# for each type, a dict of the form {<field-name-exposed-in-record>:<alchemy_accessor_name>}
+# so after that, an 'authority' record will e.g. have a 'reg-pis' field with the hrns of its pi-users
+augment_map={'authority': {'reg-pis':'reg_pis',},
+             'slice': {'reg-researchers':'reg_researchers',},
+             'user': {'reg-pi-authorities':'reg_authorities_as_pi',
+                      'reg-slices':'reg_slices_as_researcher',},
+             }
+
+def augment_with_related_hrns (local_record):
+    # search in map according to record type
+    type_map=augment_map.get(local_record.type,{})
+    # use type-dep. map to do the job
+    for (field_name,attribute) in type_map.items():
+        # get related objects
+        related_records = getattr(local_record,attribute,[])
+        hrns = [ r.hrn for r in related_records ]
+        setattr (local_record, field_name, hrns)
+    
+
index 0ac188f..6e58d10 100644 (file)
@@ -33,9 +33,16 @@ class Record:
         # fallback
         return "** undef_datetime **"
     
-    def todict (self):
+    # it may be important to exclude relationships
+    def todict (self, exclude_type=None):
         d=self.__dict__
-        keys=[k for k in d.keys() if not k.startswith('_')]
+        def exclude (k,v):
+            if k.startswith('_'): return True
+            if exclude_type:
+                if isinstance (v,exclude_type): return True
+                if isinstance (v,list) and v and isinstance (v[0],exclude_type) : return True
+            return False
+        keys=[k for (k,v) in d.items() if not exclude(k,v)]
         return dict ( [ (k,d[k]) for k in keys ] )
     
     def toxml(self):