Merge Master in geni-v3 conflict resolution
[sfa.git] / sfa / storage / model.py
index e490251..b095042 100644 (file)
@@ -1,6 +1,7 @@
 from types import StringTypes
 from datetime import datetime
 
 from types import StringTypes
 from datetime import datetime
 
+from sqlalchemy import or_, and_ 
 from sqlalchemy import Column, Integer, String, DateTime
 from sqlalchemy import Table, Column, MetaData, join, ForeignKey
 from sqlalchemy.orm import relationship, backref
 from sqlalchemy import Column, Integer, String, DateTime
 from sqlalchemy import Table, Column, MetaData, join, ForeignKey
 from sqlalchemy.orm import relationship, backref
@@ -314,11 +315,20 @@ class RegKey (Base):
 class SliverAllocation(Base,AlchemyObj):
     __tablename__       = 'sliver_allocation'
     sliver_id           = Column(String, primary_key=True)
 class SliverAllocation(Base,AlchemyObj):
     __tablename__       = 'sliver_allocation'
     sliver_id           = Column(String, primary_key=True)
+    client_id           = Column(String)
+    component_id        = Column(String)
+    slice_urn           = Column(String)
     allocation_state    = Column(String)
 
     def __init__(self, **kwds):
         if 'sliver_id' in kwds:
             self.sliver_id = kwds['sliver_id']
     allocation_state    = Column(String)
 
     def __init__(self, **kwds):
         if 'sliver_id' in kwds:
             self.sliver_id = kwds['sliver_id']
+        if 'client_id' in kwds:
+            self.client_id = kwds['client_id']
+        if 'component_id' in kwds:
+            self.component_id = kwds['component_id']
+        if 'slice_urn' in kwds:
+            self.slice_urn = kwds['slice_urn']
         if 'allocation_state' in kwds:
             self.allocation_state = kwds['allocation_state']
 
         if 'allocation_state' in kwds:
             self.allocation_state = kwds['allocation_state']
 
@@ -334,7 +344,7 @@ class SliverAllocation(Base,AlchemyObj):
         return state
 
     @staticmethod    
         return state
 
     @staticmethod    
-    def set_allocations(self, sliver_ids, state):
+    def set_allocations(sliver_ids, state):
         from sfa.storage.alchemy import dbsession
         if not isinstance(sliver_ids, list):
             sliver_ids = [sliver_ids]
         from sfa.storage.alchemy import dbsession
         if not isinstance(sliver_ids, list):
             sliver_ids = [sliver_ids]
@@ -344,7 +354,7 @@ class SliverAllocation(Base,AlchemyObj):
         sliver_ids_found = []
         for sliver_allocation in sliver_allocations:
             sliver_allocation.allocation_state = state
         sliver_ids_found = []
         for sliver_allocation in sliver_allocations:
             sliver_allocation.allocation_state = state
-            sliver_ids_found = sliver_allocation.sliver_id
+            sliver_ids_found.append(sliver_allocation.sliver_id)
 
         # Some states may not have been updated becuase no sliver allocation state record
         # exists for the sliver. Insert new allocation records for these slivers and set
 
         # Some states may not have been updated becuase no sliver allocation state record
         # exists for the sliver. Insert new allocation records for these slivers and set
@@ -356,7 +366,7 @@ class SliverAllocation(Base,AlchemyObj):
         dbsession.commit()
 
     @staticmethod
         dbsession.commit()
 
     @staticmethod
-    def delete_allocations(self, sliver_ids):
+    def delete_allocations(sliver_ids):
         from sfa.storage.alchemy import dbsession
         if not isinstance(sliver_ids, list):
             sliver_ids = [sliver_ids]
         from sfa.storage.alchemy import dbsession
         if not isinstance(sliver_ids, list):
             sliver_ids = [sliver_ids]
@@ -365,6 +375,27 @@ class SliverAllocation(Base,AlchemyObj):
         for sliver_allocation in sliver_allocations:
             dbsession.delete(sliver_allocation)
         dbsession.commit()
         for sliver_allocation in sliver_allocations:
             dbsession.delete(sliver_allocation)
         dbsession.commit()
+    
+    def sync(self):
+        from sfa.storage.alchemy import dbsession
+        
+        constraints = [SliverAllocation.sliver_id==self.sliver_id]
+        results = dbsession.query(SliverAllocation).filter(and_(*constraints))
+        records = []
+        for result in results:
+            records.append(result) 
+        
+        if not records:
+            dbsession.add(self)
+        else:
+            record = records[0]
+            record.sliver_id = self.sliver_id
+            record.client_id  = self.client_id
+            record.component_id  = self.component_id
+            record.slice_urn  = self.slice_urn
+            record.allocation_state = self.allocation_state
+        dbsession.commit()    
+        
 
 ##############################
 # although the db needs of course to be reachable for the following functions
 
 ##############################
 # although the db needs of course to be reachable for the following functions
@@ -416,3 +447,35 @@ def make_record_xml (xml):
     logger.info("load from xml, keys=%s"%xml_dict.keys())
     return make_record_dict (xml_dict)
 
     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)
+    
+