first stab at a design where each incoming API call has its own dbsession
[sfa.git] / sfa / storage / model.py
index 3f600d4..1228290 100644 (file)
@@ -191,9 +191,7 @@ 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
+    def update_pis (self, pi_hrns, dbsession):
         # strip that in case we have <researcher> words </researcher>
         pi_hrns = [ x.strip() for x in pi_hrns ]
         request = dbsession.query (RegUser).filter(RegUser.hrn.in_(pi_hrns))
@@ -221,9 +219,7 @@ 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
+    def update_researchers (self, researcher_hrns, dbsession):
         # strip that in case we have <researcher> words </researcher>
         researcher_hrns = [ x.strip() for x in researcher_hrns ]
         request = dbsession.query (RegUser).filter(RegUser.hrn.in_(researcher_hrns))
@@ -233,8 +229,9 @@ class RegSlice (RegRecord):
 
     # 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
-        from sfa.storage.alchemy import dbsession
+        from sqlalchemy.orm import sessionmaker
+        Session=sessionmaker()
+        dbsession=Session.object_session(self)
         from sfa.util.xrn import get_authority
         authority_hrn = get_authority(self.hrn)
         auth_record = dbsession.query(RegAuthority).filter_by(hrn=authority_hrn).first()
@@ -344,8 +341,7 @@ class SliverAllocation(Base,AlchemyObj):
         return state
 
     @staticmethod    
-    def set_allocations(sliver_ids, state):
-        from sfa.storage.alchemy import dbsession
+    def set_allocations(sliver_ids, state, dbsession):
         if not isinstance(sliver_ids, list):
             sliver_ids = [sliver_ids]
         sliver_state_updated = {}
@@ -366,8 +362,7 @@ class SliverAllocation(Base,AlchemyObj):
         dbsession.commit()
 
     @staticmethod
-    def delete_allocations(sliver_ids):
-        from sfa.storage.alchemy import dbsession
+    def delete_allocations(sliver_ids, dbsession):
         if not isinstance(sliver_ids, list):
             sliver_ids = [sliver_ids]
         constraint = SliverAllocation.sliver_id.in_(sliver_ids)
@@ -377,8 +372,10 @@ class SliverAllocation(Base,AlchemyObj):
         dbsession.commit()
     
     def sync(self):
-        from sfa.storage.alchemy import dbsession
         
+        from sqlalchemy.orm import sessionmaker
+        Session=sessionmaker()
+        dbsession=Session.object_session(self)
         constraints = [SliverAllocation.sliver_id==self.sliver_id]
         results = dbsession.query(SliverAllocation).filter(and_(*constraints))
         records = []
@@ -447,3 +444,35 @@ 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_sfa_builtins (local_record):
+    # don't ruin the import of that file in a client world
+    from sfa.util.xrn import Xrn
+    # add a 'urn' field
+    setattr(local_record,'reg-urn',Xrn(xrn=local_record.hrn,type=local_record.type).urn)
+    # users have keys and this is needed to synthesize 'users' sent over to CreateSliver
+    if local_record.type=='user':
+        user_keys = [ key.key for key in local_record.reg_keys ]
+        setattr(local_record, 'reg-keys', user_keys)
+    # 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)
+    
+